I can’t get Supabase real-time listen to Postgres changes to work - supabase

Inspired by the Supabase docs, I have this code in a React Native app:
useEffect(() => {
if (session?.user?.id === null) return
const channel = supabase
.channel('value-db-changes', { selfBroadcast: true })
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'messages',
filter: `user_id=${session?.user?.id}`
},
(payload) => console.log('Supabase change', payload)
)
?.subscribe()
}, [session?.user?.id])
VSCode warns me that Property 'subscribe' does not exist on type 'never' and the console.log never shows as I edit rows in my database.

You might be using the old version of Supabase but trying v2 syntax.
Supabase v1 documentation for realtime:
https://supabase.com/docs/reference/javascript/subscribe
As per the latest update for v2 - https://supabase.com/blog/supabase-js-v2,
// v2
supabaseClient
.channel('any_string_you_want')
.on(
'postgres_changes',
{
event: 'INSERT',
schema: 'public',
table: 'movies',
},
(payload) => {
console.log(payload)
}
)
.subscribe()
// v1
supabase
.from('movies')
.on('INSERT', (payload) => {
console.log(payload)
})
.subscribe()
I had similar issues with this code, but installing the right version with v1 syntax worked,
npm uninstall #supabase/supabase-js#rc
npm uninstall #supabase/supabase-js
npm install #supabase/supabase-js

Hi 👋🏼 from comparing your code snippet with the supabase docs, it should generally work.
I'm assuming your listener isn't triggered because one of those:
filter is too specific and your changes don't trigger it: e.g. are you editing the messages table with the same user.id that you're listening to?
the selfBroadcast option isn't in the Supabase docs and quick internet search didn't bring it up as well
As a first step I would set up the broadest subscription and test if this one is triggered and what's in the payload. Then step by step create the filter to only listen to the events that are of interest.
const mySubscription = supabase
.from('*')
.on('*', payload => {
console.log('Change received!', payload)
})
.subscribe()

Related

Strapi : Email setting fields seems to be disabled mode. How to enabled this

I am using latest version of strapi (v4.0.0)
In Email settings ---> fields seems to be disabled
How to enable this fields
Well, those fields are readonlyand are only configurable via the plugins.js file. Create the following file:
// filepath - config/plugins.js
module.exports = ({ env }) => ({
// ...
email: {
config: {
provider: 'sendmail',
settings: {
defaultFrom: 'myemail#protonmail.com',
defaultReplyTo: 'myemail#protonmail.com',
},
},
},
// ...
});
Once done, just start the strapi server again using yarn develop command and you should see your values being reflected in the admin. Then you can even try sending out a test email using the Send Test Email button.
Reference:
Strapi Email Plugin

Spartacus Storefront Multisite I18n with Backend

We've run into some problems for our MultiSite Spartacus setup when doing I18n.
We'd like to have different translations for each site, so we put these on an API that can give back the messages dependent on the baseSite, eg: backend.org/baseSiteX/messages?group=common
But the Spartacus setup doesn't let us pass the baseSite? We can
pass {{lng}} and {{ns}}, but no baseSite.
See https://sap.github.io/spartacus-docs/i18n/#lazy-loading
We'd could do it by overriding i18nextInit, but I'm unsure how to achieve this.
In the documentation, it says you can use crossOrigin: true in the config, but that does not seem to work. The type-checking say it's unsupported, and it still shows uw CORS-issues
Does someone have ideas for these problems?
Currently only language {{lng}} and chunk name {{ns}} are supported as dynamic params in the i18n.backend.loadPath config.
To achieve your goal, you can implement a custom Spartacus CONFIG_INITIALIZER to will populate your i18n.backend.loadPath config based on the value from the BaseSiteService.getActive():
#Injectable({ providedIn: 'root' })
export class I18nBackendPathConfigInitializer implements ConfigInitializer {
readonly scopes = ['i18n.backend.loadPath']; // declare config key that you will resolve
readonly configFactory = () => this.resolveConfig().toPromise();
constructor(protected baseSiteService: BaseSiteService) {}
protected resolveConfig(): Observable<I18nConfig> {
return this.baseSiteService.getActive().pipe(
take(1),
map((baseSite) => ({
i18n: {
backend: {
// initialize your i18n backend path using the basesite value:
loadPath: `https://backend.org/${baseSite}/messages?lang={{lng}}&group={{ns}}`,
},
},
}))
);
}
}
and provide it in your module (i.e. in app.module):
#NgModule({
providers: [
{
provide: CONFIG_INITIALIZER,
useExisting: I18nBackendPathConfigInitializer,
multi: true,
},
],
/* ... */
})
Note: the above solution assumes the active basesite is set only once, on app start (which is the case in Spartacus by default).

GraphQL Nexus Schema (nexusjs) doesn't compile with scalar types

I am trying to follow the documentation on the Nexus-Schema (nexusjs) website for adding scalar types to my GraphQL application.
I have tried adding many of the different implementations to my src/types/Types.ts file using the samples provided in the documentation and the interactive examples. My attempts include:
Without a 3rd party libraries:
const DateScalar = scalarType({
name: 'Date',
asNexusMethod: 'date',
description: 'Date custom scalar type',
parseValue(value) {
return new Date(value)
},
serialize(value) {
return value.getTime()
},
parseLiteral(ast) {
if (ast.kind === Kind.INT) {
return new Date(ast.value)
}
return null
},
})
With graphql-iso-date 3rd party library:
import { GraphQLDate } from 'graphql-iso-date'
export const DateTime = GraphQLDate
With graphql-scalars 3rd party library (as shown in the ghost example):
export const GQLDate = decorateType(GraphQLDate, {
rootTyping: 'Date',
asNexusMethod: 'date',
})
I am using this new scalar type in an object definition like the following:
const SomeObject = objectType({
name: 'SomeObject',
definition(t) {
t.date('createdAt') // t.date() is supposed to be available because of `asNexusMethod`
},
})
In all cases, these types are exported from the types file and imported into the makeSchema's types property.
import * as types from './types/Types'
console.log("Found types", types)
export const apollo = new ApolloServer({
schema: makeSchema({
types,
...
context:()=>(
...
})
})
The console.log statement above does show that consts declared in the types file are in scope:
Found types {
GQLDate: Date,
...
}
If I run the app in development mode, everything boots up and runs fine.
ts-node-dev --transpile-only ./src/app.ts
However, I encounter errors whenever I try to compile the app to deploy to a server
ts-node ./src/app.ts && tsc
Note: This error occurs occurs running just ts-node ./src/app.ts before it gets to tsc
The errors that shown during the build process are the following:
/Users/user/checkouts/project/node_modules/ts-node/src/index.ts:500
return new TSError(diagnosticText, diagnosticCodes)
^
TSError: ⨯ Unable to compile TypeScript:
src/types/SomeObject.ts:11:7 - error TS2339: Property 'date' does not exist on type 'ObjectDefinitionBlock<"SomeObject">'.
11 t.date('createdAt')
Does anyone have any ideas on either:
a) How can I work around this error? While long-term solutions are ideal, temporary solutions would also be appreciated.
b) Any steps I could follow to debug this error? Or ideas on how get additional information to assist with debugging?
Any assistance would be very much welcomed. Thanks!
The issue seems to be resolved when --transpile-only flag is added to the nexus:reflect command.
This means the reflection command gets updated to:
ts-node --transpile-only ./src/app.ts
and the build comand gets updated to:
env-cmd -f ./config/.env ts-node --transpile-only ./src/app.ts --nexusTypegen && tsc
A github issue has also been created which can be reviewed here: https://github.com/graphql-nexus/schema/issues/690

Unit testing: getText is not a function

I'm new to unit testing and I'm trying to select an ID to select its text and check if it equals 'Inbox'. I'm getting a
TypeError in "User visits Quick Add Task starts with a blank task" elem.getText is not a function
and I don't understand why.
Test source code here.
describe('User visits Quick Add Task', () => {
it('starts with a blank task', () => {
browser.url('http://localhost:8080/');
const elem = $('#inbox-clickable');
console.log(elem.getText());
assert.equal(elem.getText(), 'Inbox');
})
});
For me the solution to a very similar problem was adding the missing #wdio/sync package to my package.json.
I already had previously added sync: true, to my wdio.conf.js and remove all async and await from my testing code.

Why can't I use `useMasterKey()` in a `beforeSave` function?

My Parse app has a GiftCode collection which disallows the find operation at the class-level.
I am writing a beforeSave cloud function that prevents duplicate codes from being entered by our team from Parse's dashboard:
Parse.Cloud.beforeSave('GiftCode', function (req, res) {
Parse.Cloud.useMasterKey();
const code = req.object.get('code');
if (!code) {
res.success();
} else {
const finalCode = code.toUpperCase().trim();
req.object.set('code', finalCode);
(new Parse.Query('GiftCode'))
.equalTo('code', finalCode)
.first()
.then((gift) => {
if (!gift) {
res.success();
} else {
res.error(`GiftCode with code=${finalCode} already exists (objectId=${gift.id})`);
}
}, (err) => {
console.error(err);
res.error(err);
});
}
});
As you can see, I am calling Parse.Cloud.useMasterKey() (and this is running in the Parse cloud), but I am still getting the following error:
This user is not allowed to perform the find operation on GiftCode.
I use useMasterKey() in other normal cloud functions and am able to perform find operations as needed.
Is useMasterKey() not applicable to beforeSave functions?
I've never tried to use the master key in a beforeSave function but I wouldn't be surprised if there's some extra safeguards in place to prevent it. From a security standpoint, it seems like it could make all write-based CLPs and ACLs worthless for that class.
Try selectively using the master key by passing it as an option to the query like so
(new Parse.Query('GiftCode'))
.equalTo('code', finalCode)
.first({ useMasterKey: true })
.then((gift) => {
...
Parse.Cloud.useMasterKey(); has been deprecated in Parse Server version 2.3.0 (Dec 7, 2016). From that version on, it is a no-op (it does nothing). You should now insert the {useMasterKey:true} optional parameter to each of the methods that need to override the ACL or CLP in your code.

Resources