vulcanjs / vulcan-npm Goto Github PK
View Code? Open in Web Editor NEWThe full-stack JavaScript App Framework
Home Page: https://vulcan-docs.vercel.app
License: MIT License
The full-stack JavaScript App Framework
Home Page: https://vulcan-docs.vercel.app
License: MIT License
In order to make ListMdxFiles recursive, we should decide how we handle the index.md
files, or if we handle them.
For example, /docs/nest/index.md
should resolve to /docs/nest
instead of /docs/nest/index
.
This was the object planned... if I'm correct.
interface MdxFile {
fileName: string; // filename with extension
relativePath: string;
pageName: String
}
Is your feature request related to a problem? Please describe.
strictNullCheck improves code quality a lot, and you don't want to activate it late in the project because it may require a lot of change
Describe the solution you'd like
Activate and fix the issues
Cross-post from VulcanJS/Vulcan#2640
{ data: { foo : { result: <your-foo>
}, result: }}`{ data: { foo : { results: <your-foo>
}, results: }}`{ data: { foo : { data: <your-foo>
}, document: }}`{ data: { foo : { document: <your-foo>
}, document: }}`{ data: { foo : { documents: <your-foo>
}, documents: }}`{ data: { foo : { document: <your-foo>
}, document: }}`This way we use document
as the canonical name for the object we are modifying ; we remove the confusing result
name, and we use data
only for generic data (eg the response of apollo query that contains both documents and metadata)
Is your feature request related to a problem? Please describe.
Is your feature request related to a problem? Please describe.
There is no dev mode so we must manually rebuild.
Describe the solution you'd like
yarn run dev
should run the build system in watch mode, in order to rebuild relevant package on change
Describe alternatives you've considered
Check Lerna documentation for how we can do that, or existing Lerna project like Babel, Jest...
Work in progress in branch feature/resolvers
asAdmin
option to bypass restrictionsnew SimpleSchema(schema)
works when there are nested fields to, or if we must call it for each field also => done, in schema we must remove calls to new SimpleSchema
throwError
functionBranch: feature/vulcan-server
Is your feature request related to a problem? Please describe.
Apollo Client 3.4.2 allows to pass variables and context into the update function => might be easier to write the multi updater, without the hack we use currently to find the queries?
https://github.com/apollographql/apollo-client/releases?after=v3.4.2
This concerns the development environment, when one want to test the local version of Vulcan NPM in a Vulcan app.
facebook/react#13991
facebook/react#14257
https://stackoverflow.com/questions/34706817/how-prevent-multiple-copies-of-react-from-loading
https://next.material-ui.com/getting-started/faq/#duplicated-module-in-node-modules
https://robkendal.co.uk/blog/2019-12-22-solving-react-hooks-invalid-hook-call-warning
Using npm link
or yarn link
on Lerna packages ends up loading 2 versions of React and React Dom. We might avoid this by making React and React DOM peer dependencies, or using more robust commands in Vulcan Next
Current fix:
Vulcan NPM
, run cd node_modules/react && yarn link
, same with react-dom
or any problematic duplicate packageyarn link react
, yarn link react-dom
, etc. with any problematic library. This way the Vulcan NPM version will be preferredAlternative: using Webpack but that's not good.
Possible solution:
Allow to pass a VULCAN_PACKAGE_DIRS env variable like we did in Meteor and handle yarn link
ourselves, so the end user doesn't need to know it.
Is your feature request related to a problem? Please describe.
When the cookie
https://developer.mozilla.org/fr/docs/Web/HTTP/Headers/Set-Cookie/SameSite
Describe the solution you'd like
Possibility to configure the SameSite parameter + documentation on how to have the API and the frontend on different domain, eg for a shared API.
It can also affects app with a Meteor backend and a Next frontend.
Describe alternatives you've considered
Hosting on the same root domain should solve this issue.
Additional context
Add any other context or screenshots about the feature request here.
Is your feature request related to a problem? Please describe.
Similar to a SmartForm, but instead of creating/editing, specialized for searching and filtering.
Describe the solution you'd like
The schema would need a few more fields to define the possible values for some types (eg for a range, define min and max you want to see.
They could also be computed by an async callback (if you want to compute a $distinct, a min/max for a dynamic range).
Is your feature request related to a problem? Please describe.
@see https://stackoverflow.com/questions/63058081/package-json-with-multiple-entrypoints
@see https://blog.mozilla.org/data/2021/04/07/this-week-in-glean-publishing-glean-js/
This would allow us to use index.server.ts
files instead of server/index.ts
, and get rid of the typesVersions
hack we currently use to handle both server and client exports.
Also see this Lerna ticket for the "fake alias" hack: @see lerna/lerna#3006
Describe the bug
We have a function to get the document to update in default mutations, but also in the mutators:
getMutationDocument
)Shouldn't we remove the one in the default mutation?
Describe the bug
Because of Mongo memory server, we hit this issue:
nodkz/mongodb-memory-server#475
https://stackoverflow.com/questions/67699988/mongo-memory-server-is-not-starting-at-all
To Reproduce
Run tests on windows
Describe the problem you want to solve or enhancement you want to bring
Development of Vulcan NPM can become tricky when you want to experiment it in a real app, like in Vulcan Next. We need to use Yalc etc.
Having only one repo containing Vulcan core logic (NPM) + demo apps (Next, Express, Gatsby...) makes it easier to develop the framework.
Cons: can't the monorepo becomes a mess of complicated apps?
Define relevant concepts
Blitz is structured as a monorepo but revolves a lot around the Next app. We'd want to do the reverse: putting Vulcan Next within the monorepo.
Describe your solution
We could have scripts to create apps, based on templates => npx create-vulcan-app next
generate a Next app, a Gatsby app, etc.
We could also keep separate repos like Vulcan Next, but generate them automatically. So that developers can still simply clone Vulcan Next for instance and get the latest code.
Questions to the community
npx create-vulcan-app next
?npx create-vulcan-app
or npx vulcan create next
?Describe the bug
I can't find a way to have breakpoints to work
To Reproduce
Set a breakpoint ina component and run "Jest current file" debugger => your breakpoint is not reckognized, with either "source map problem" or "breakpoint set but not yet bound message".
Expected behavior
Debugger is able to find the source maps and breakpoints.
Additional context
The TS Webpack setup is tricky:
.js
versionI wonder if VS code expects one source map per file, which would be weird. Maybe it fails to detect that "index.js" is the built file and that it's where it should look (and instead fetch Form.js or Form.js.map which doesn't exist).
Is your feature request related to a problem? Please describe.
Unit test may let pass the case where we forget to correctly export files in the NPM package.
We absolutely need to run yarn run build
locally before publishing packages, so we need a way to secure this process.
Describe the solution you'd like
We could have multiple strategies, like running npm pack --dry-run
.
We can also add a publish
+ prepublish
script that forces the build, but that can be annoying when you have already built the app and want to skip this step. I'd rather check if the build has been done, than systematically building.
To reproduce
Run yarn clean
then npm pack --dry-run
in a package => you will have an empty result because /dist
folders are empty.
We could also simply check that all packages contain a "dist" folder or something similar.
Is your feature request related to a problem? Please describe.
Based on Vulcan existing DataTable
In combination with the datatable, we can make "exploring" views.
Describe the bug
Updating user form fields gives the following error:
Cannot query field "userId" on type "User". Did you mean "username"?, Location: line 14, col 3, Path: undefined
To make it work, you have to manually add userId
to your User schema.
The default fragment somehow systematically includes userId but User is an exception: it doesn't have an userId in its schema
To Reproduce
Steps to reproduce the behavior:
meteor-demo.tsx
, using useUpdate({model: User})
.Expected behavior
The form should successfully update user fields without any modification to the user schema
Here is my demo form that was not working:
import {
useUpdate,
} from "@vulcanjs/react-hooks";
import { User } from "../../models/meteorUser";
const ProfileForm = (props) => {
const [updateDocument] = useUpdate({ model: User });
if(props.user){
return (
<form
onSubmit={async (evt) => {
evt.preventDefault();
evt.stopPropagation();
const displayName = (evt.target as any).displayName.value;
// const url = (evt.target as any).url.value;
await updateDocument({
input: { id: props.user._id, data: { displayName } },
});
}}
>
<input
placeholder="name"
type="text"
name="displayName"
defaultValue={props.user.displayName}
/>
<button type="submit">Update</button>
</form>
);
}else{
return null
}
};
export default ProfileForm
Is your feature request related to a problem? Please describe.
Some fields are using constructors such as String
, Boolean
...
Describe the solution you'd like
This way we can store schemas.
Additional context
Add any other context or screenshots about the feature request here.
Is your feature request related to a problem? Please describe.
I am exploring modern alternatives to Babel/Webpack for a faster build time.
First experiment is on the react-ui
package.
Describe the solution you'd like
- Need to be able to output code for Node (during SSR) and the browser (for React components)
- Need to generate .d.ts?
tsc
or ts-loader
. See swc-project/swc#657Describe alternatives you've considered
Next.js is backing SWC, so it's expected to have a lot of updates.
Be careful that SWC is a parser, so a replacement to Babel, not to Webpack. They are building "SWCpack" for this purpose but it's not there yet.
Dumping Babel may have some consequences, see vercel/next.js#30174, as SWC doesn't support all packages yet and have a smaller ecosystem.
It proposes a Webpack loader => great for fast setup by replacing babel-loader
.
We need to figure the .d.ts generation thing.
Seems to work ok, very fast. But since Next is preferring SWC, that is written in Rust (Esbuild is in Go, so great language but less relevant for a build tool), we might go the Next.js way.
Not completely sure how it replace Babel/Webpack. But I am sure it doesn't correctly support .d.ts either: evanw/esbuild#95
Additional context
Add any other context or screenshots about the feature request here.
Is your feature request related to a problem? Please describe.
Connector is a more direct connection to the db, but it doesn't use Vulcan "magic" and callbacks. They are internal to Vulcan and should not be used in user apps.
Mongoose models are ok for direct connection to the db, it's ok to use them but also won't run the callbacks.
Mutators will run Vulcan callbacks and permission checks, they are better suited for custom mutations.
We need an equivalent for queries, "Queriers". In particular, the querier should run permission check and remove unallowed fields.
Describe the solution you'd like
Normally, mutators do not depend on the request context, and should not use DataSources (they are only needed for field query resolvers, not for mutations), so the graphql context should not be a problem. It used to be an issue in Vulcan Meteor but that was because we used the GraphQL context wrongly.
Probably related to #5
It looks like there are several instances of `@material-ui/styles` initialized in this application.
This may cause theme propagation issues, broken class names, specificity issues, and makes your application bigger without a good reason.
See https://material-ui.com/r/styles-instance-warning for more info.
We need to use the version from vulcan-npm most probably.
Is your feature request related to a problem? Please describe.
useMulti is now using a client-side filtering system, but sometimes you might want server-side terms.
Describe the solution you'd like
Reintroduce old "terms" system, but only for advanced filters this time.
Describe alternatives you've considered
Additional context
Add any other context or screenshots about the feature request here.
Is your feature request related to a problem? Please describe.
Our connectors are not very smart about the field they query
Describe the solution you'd like
Adding an optional "projection" parameter to connector, for find
, findOne
...
Describe alternatives you've considered
Mongo/Mongoose often takes the projection as the second parameter: selector, then projection, then options (sort, limit).
In Vulcan the order would be slightly different: selector, options, projection. This makes more sense because projection is less used in custom resolvers.
Is your feature request related to a problem? Please describe.
In the SmartForm, we want to display a blocking popup "You have unsaved changes, are you sure you want to leave" on various events: closing the browser, changing route.
The problem is that "changing" route can happen at 2 levels:
The problem is that SPA route transition are handled by a router, which is framework specific. React Router was suffering from this limitation, and Next also suffers from it: you have to use a framework specific solution to block the route transitions.
Describe the solution you'd like
For instance in React Router, that means calling history.block()
, in Next, adding a listener to "beforepopstate"
Demo of a generic hook: https://gist.github.com/eric-burel/75301e2ba01967e0ec909ddf7fae5100
Work ongoing there: #31
Describe alternatives you've considered
It's possible to have Next specific solution but that creates a tight coupling which we refuse
Additional context
In Vulcan, commit "3ac1a60b62fb78fd1d71d72f00b11172f34a0ed4" replaced cache
by client
in Apollo multi query updater.
For the record, this function updates list when you create a new item locally.
As a default, Apollo only provides you the cache. That's enough in most case, but updating the cache WON'T update watched queries. In this case, you have to call writeQuery
on the client
object and not just the cache
Our current implementation of Apollo client, and the method to access it, relies on @vulcan/next-apollo
, which is a Next specific package (see #6), but we don't want @vulcan/react-hooks
to depend on it.
The problem is that Apollo doesn't really provide a way to access the default Apollo client either, and does not include it in the update
call parameter.
Technically, since you are in the mutation, there is such a client, it is just not exposed in the API.
To be fully solved, this issue must be solved at Apollo client level. Another solution is that the cache should actually trigger watched queries too?
Possibly related:
Ability to write full-stack "feature-oriented" packages with both server and client features, in NPM, as we are used to do in Meteor.
@vulcanjs/graphql
is a good example of this, as it generates the graphql backend, the client fragments, and both are very tied.
Meteor packages are example of fullstack package with their client
and server
logic.
This is different from just having code that works everywhere, like a low-level library. We are talking about code that is actually specific to the env (calling window
on the client for instance).
We should be able to do something like import createServer from "@vulcanjs/graphql/server"
, import someHook from "@vulcanjs/graphql/client"
and import someSharedCode from "@vulcanjs/graphql"
Example: a full-stack package could expose @vulcanjs/graphql/server
and @vulcanjs/graphql/client
. An isomorphic import would be import foobar from "@vulcanjs/graphql"
and let the the build system add /client
or /server
depending on the context.
Meteor is also doing that.
Limitation: the text editor can't know the environment where the code is run. So, for static typing, you have to explose a generic version. Meteor is subject to this limitation.
Blitz.js has something similar, but with "unbalanced isomorphism", limited to how they consume the server using a custom query
system. The typing is coming from the server, that contains the actual logic, as the client version is just a dull wrapper that does an HTTP call.
True isomorphism: you write a single piece of code and let the build system modify it depending on the execution environment. Next pages
fall into this category. getServerSideProps
and getStaticProps
functions exported in a page are server-only methods. The rest React (so client but also compatible with server-side rendering). At build time, those methods are removed from the client bundle.
This is something we would want to achieve for Vulcan model's:
const Foo = createModel({
schema: {
foobar: {
type: string; // both client and server, to render form, generate the gql schema etc.
resolver : () => {...} // field resolver, server-only
onCreate: () => {...} // server-only
}
},
queries: { ... },
mutations: { ... } // CRUD operations, server-only
})
In this example, the schema mixes shared elements, like the type for "Foo.foobar", and server only methods like the graphql resolver.
The power of Vulcan is to let you write only one schema with everything. The limitation is that you don't want the client bundle to contain server code, and sometimes vice-versa. You can bypass this with ugly require
or playing around with GraphQL context, but only so much.
First step is implementing full-stack packages.
Then isomorphic import could be kept as a "magic" helper specific to Vulcan. But it is not mandatory (like if you create an Express server and don't use weback, you just do import foobar from "@vulcanjs/graphql/server"
as usual). This feature is more comfort for people used to Meteor.
For full-stack package: Multi entry Webpack export/TypeScript. It should not be too hard, but I've never done that before, there are a lot of moving pieces. So help welcome!
For isomorphic import: there is a demo package multi-env
that does exactly this. The way it works, it imports either index.server
or index.client
, using Webpack magic.
For the text editor autocompletion, or common code, we can also add an index
that exports both. That's a prototype so again help and feedback welcome.
A good example to get started is the graphql
package, that contains both server and client logic.
For true isomorphism: it's not easy at all to mix server and client stuff at the same place.
foobar.ts
:export const schema = { foobar: {...} } // the common part
export const fieldResolvers = {foobar: {...}} // server-only. We have to repeat the field names
export const resolvers = {... } // server-only
// etc.
And then you create the full model using some build time magic. This is still a bit blurry, that's the part that require the most thinking.
developit/unfetch#104
developit/unfetch#122
We should either improve the typeScript/webpack build process.
Switching to cross-fetch does not work, as unfetch is probably also a dependency of a subpackage.
We might need to define window
as global variable, set to undefined, in webpack.
Building packages meant specifically for Next is specific.
We probably don't need to have a full build process, and we should instead let Next do it's magic as much as possible, directly within the Next user app.
Exactly like a Meteor package does not necessarily need a lot of transpiling to be published.
See this discussion for example, regarding process.env
in NPM packages: vercel/next.js#17262
I did a test with next-transpile-modules
but did not manage to make it work as expected yet: martpie/next-transpile-modules#120
At the moment, Next packages specific to vulcan are shipped directly with the starter, they are not real NPM packages.
Is your feature request related to a problem? Please describe.
Currently you cannot write { input: { filter: { foo: 2}=}
in a multi filter. You have to use the _eq
operator { input: { filter: { foo: {_eq:2 }}}}
.
Describe the solution you'd like
Allow a shortcut syntax for those fields. See the FieldSelector
type in packages/graphql/typings.ts
, I've commented the native values and only allow a condition.
Describe alternatives you've considered
I think the problem is that you cannot have union types for input in Graphql: it's difficult to accept both an object or a native value as input. To be confirmed.
Is your feature request related to a problem? Please describe.
Imagine you have Todo and User models. A User can have multiple Todos. A Todo can have only one User, its owner.
To create a relationship from Todo to User, you need to a have a field Todo.userId
. You then use the hasOne
helper to create a resolver able to fetch User related to a Todo.
But if you want the reverse, you have 2 patterns:
You add a field User.todoIds
. You use hasMany
on this field. Limit: it is quite difficult to keep both data in sync. You have to keep track of the Todo userId
but also update the User todoIds
on each mutation.
We technically are already able to code this with hasOne
hasMany
and callbacks.
You add User.todos
and create a resolver that can fetch the todos based on Todo.userId
. Limit: it is more costly, as you need to find all users todos among all possible todos. You probably need to set an index on Todo.userId
in your Mongo db to make this efficient.
For this pattern, we currently don't have any helper.
Describe the solution you'd like
A way to define hasOne
or hasMany
relationship WITHOUT creating a new field containing ids, in order to keep a single source of truth.
Note: even if we use Mongo, those are relational patterns. We don't really use the NoSQL approach of Mongo in Vulcan, so that's fine to use patterns you would find traditionally in SQL DBMS.
In Hasura, you can select the reference schema of a relationship. It can be either the current schema, which is equivalent to pattern "1.". But it can also be a different schema, which is equivalent to pattern "2.".
Describe alternatives you've considered
For pattern 1., the current syntax is fine, but you need to define the callbacks carefully. We can keep it as is.
For pattern 2., we could provide some relation
syntax.
Multiple syntaxes are possible, for example:
todos: {
...
relation: {
model: Todo, // model where to look for data
from: "_id", // field in the current schema to compare
to: "userId", // field in the reference schema
kind: 'hasMany'
}
The generated resolver will simply run a query on Todo
collection to find relevant data.
We could also use the normal resolveAs
syntax but provide an helper to create the resolver:
todos: {
resolveAs: {
resolver: arrayRelationResolver({from: "_id", to: "userId", targetModel: Todo})
Based on VulcanJS/Vulcan#2638 and VulcanJS/Vulcan#2672
Like we do in Next, we shouldn't need to explicitely import React in any .tsx file
packages/react-ui/components/form/FormComponentInner.tsx
packages/react-components/components/form/Form/fields.ts
, move the side effect of handleFieldPath
(default value setting) somewhere else, to make the function pure./Form
, we have a circular dependency with packages/react-ui/components/form/defaultVulcanComponents.ts, not sure how to fix it... Currently we hard copy the Form folder to Form2 to duplicate the components but that's not very good.... => solution is to split the context provider with default component from the context consumer with the hooks, this avoids having an explicit circular dependencygetLabel
context, eg in packages/react-components/components/form/FormError.tsxwarnOnUnsavecChanges
feature (we need to figure what is the history
object exactly + stop triggering the message on page leave. We might need to recode the history.block feature?FormGenerator
between SmartForm
and Form
=> FormGenerator
would generate the whole form while Form
would focus on form management. It would allow to have 3 behaviour:SmartForm
Form
currently)It is already possible to use a custom component as input:
{
type: String,
input: MySuperReactInput
}
Limitation is that you cannot override this component using the context, it's hard written in your schema.
We could allow something like this:
{
type: String,
input: "MyCustomInput"
}
The advantage of this pattern is that you can change "MyCustomInput" from the context, as other Vulcan inputs. It can be interesting if you want to implement an API that allows some component swapping or programming a multitenant app.
You basically can create your own Vulcan app.
Limitation is that this pattern, which already exists in Vulcan Meteor, tends to be deadly over-used: since the reference to the component is implicit, you may unknowingly create circular dependency, reference a component that doesn't exist etc.
So I am not in a hurry to add this feature. This might need another ticket.
It's not clear in Apollo whether the generic type "TData" refers to the type of "document" or type of the response.
For example, if it refers to the document, we could have TData = { hello: string }
, so it matches the schema. If it refers to the data, we could have TData = { data: { createFoo : { document: { hello: string }}
, so TData would vary amongs mutations.
The second case is more likely in Apollo. But what we want in Vulcan is the first case. We should introduce a new TModel
generic which is the type of the model, and try to build the corresponding "TData" automatically.
The biggest issue is that the name of the resolver is dependent on the model (createFoo
, createBar
), it is not static so hard to precompute in typescript.
Is your feature request related to a problem? Please describe.
Source maps are not displayed when using the package, eg useMulti.
Ideally, they should provide better information when there is an error.
Describe the solution you'd like
Investigate if we should or should not add source maps to the packages, and why they don't show up already with inline production source maps.
Is your feature request related to a problem? Please describe.
When developping Vulcan NPM, all local packages are known by other packages.
It makes it difficult to detect when there is a missing dependency. For instance, say that @vulcanjs/graphql
depends on @vulcanjs/i18n
. During development, you won't have any problem, even if you forget to add the dependency to @vulcanjs/i18n
in @vulcanjs/graphql
package.json.
Describe the solution you'd like
Find a way to detect missing dependencies as well as unused dependencies in a Lerna mono repo.
Cross post of VulcanJS/Vulcan#2549
Goal is to replace the dynamic Component replacing pattern by explicit exports that would "magically" replace components.
Imagine a component structured like this:
// datatable.js
const DatatableHeader = () => (<header>default header</header>)
const DatatableFooter = () => (<footer>default footer</footerr>)
const DatatableContent = ({children}) => (
<div>
<DatableaHeader />
{children}
<DatatableFooter />
</div>
const Datatable = () => (
<div>
<DatatableContent />
</div>
)
You may want to replace the Header, and the Content with your own components:
// my-overrides.js, a special file that contains my Vulcan components override. Could be detected at build time.
export * from "vulcan/ui-react" // magically imports DatatableFooter, DatatableHeader, DatatableContent and Datatable
export const DatatableHeader = () => (<header> I AM OVERRIDEN </header>) // first override
export const DatatableContent = () => (<div><DatatableHeader/> <div> Hello </div> <DatatableFooter /></div> // second override
Then you consume them like this, business as usual:
// my-page.js
import { Datatable } from "vulcan/ui-react" // import default components + my custom override
export const MyPage = () => (<Datatable>Hello!</Datatable>) // DatatableContent has magically been replaced in Datatable
It's probably undoable with Meteor, but it could prove doable with Webpack.
The tricky part is that you want to override only certain component, that are themselves nested into other replaceable component. You get a kind of recursive/circular import issue.
This pattern is already implementable with one level of imports like this:
// my-ui.js
export * from "vulcan/react"
export const DatatableHeader = () => (...) // will reexport, overriding default DatatableHeader from "vulcan/react"
but it's not enough to handle more deeply nested component replacement, for complex components like DataTable or SmartForm that have multiple layers of replaceable component.
First step is defining a syntax for magic components.
Possibilities:
Prefixing components, eg <@Datatable>
: can be detected component by component but it's not very clean
"Magic import syntax", eg import { ComponentToReplace } from "vulcan/magic-component"
/ export * from "vulcan/magic-components"
: detect that we want to import "magic components" or override them
a special file name for files that exports component override
explicitely declaring dependencies between components eg export { component: Datatable, dependsOnMagic: ["DatatableContents"] }
The difficulty is to handle deeply nested replaceable component.
Datatable
is defined with default componentsDatatableFooter
is overridden by userDatatableContents
with overridden DatatableFooter
exportDatatable
, which depends on DatatableContents
which contains an overridden export.The build would probably look like a recursive structure or a tree, where we rebuild everything until all nested components are replaced by user's overrides.
Describe the bug
VulcanJS/Vulcan#2727
https://stackoverflow.com/questions/45227332/is-it-possible-to-implement-multiple-interfaces-in-graphql
We use "," instead of "&" syntax for multiple interfaces: right syntax is type foobar implements Duck & Boat
. We need to add a test for this scenario and fix the bug
Is your feature request related to a problem? Please describe.
Meteor uses string ids as a default: https://docs.meteor.com/api/collections.html
idGeneration String
The method of generating the _id fields of new documents in this collection. Possible values:
'STRING': random strings
'MONGO': random Mongo.ObjectID values
But Mongo uses Mongo.ObjectID.
So in Vulcan NPM:
This leads to issues with isomorphic methods like Users.owns
Describe the solution you'd like
Use string ids as a default?
Or converting?
Describe alternatives you've considered
We may want to alter the connector so it uses string ids.
I think the best way is to do this on creation, but it could be safer to do it during find. Connectors are expected to return the same type whatever the technology, so we can expect Mongoose connector to return string _id.
The problem arise in custom resolvers, if user want to call Mongo methods, they may accidentally return an ObjectId. Maybe TypeScript can catch this already?
=> this might be necessary anyway at least for "find" and "findOne", for typing consistency, connectors should return a VulcanDocument so a string _id
Simplest approach might be to introduce a compareIds
method that uses useEqual
under the hookd, and use it whenever needed + improve VulcanDocument
typing so it can be either string or ObjectId (but beware of not introducing dependency to mongo).
This is a bit annoying client-side though, where _id is guaranteed to be a string.
The problem is that it alters mongoose default behaviour. The good part is that it will guarantee string ids everywhere even for custom calls.
We need to avoid circular dependencies between NPM packages.
make the "model" unaware of graphql and mongo, it just knows its schema. Then, when we create the model, we give the possibility to enhance it, eg with graphql and mongo. That's probably the cleanest, but does that make sense ? A Vulcan model will never live without a persistence solution or even without graphql, in a foreseable future
I put the model related things, like graphql fragment generation or mongoose schema generation, in a single NPM package. So for instance "@vulcan/graphql" is just a bunch of helpers unaware of Vulcan, and "@vulcan/model/graphq" contains the logic Currently that makes sense, because those concepts are actually deeply tied. But that's not the best solution for the future.
2 is convenient and easier to implement.
1 is however the best architecture, so that we can swap technologies. This means adding potential extensions to the model.
Edit: I've tried second solution, with graphql being an extension of the Model. I'd like the final type (raw VulcanModel
, VulcanGraphqlModel
etc.) to be inferred from the included extensions, but not sure it's doable in TypeScript.
Probably an instance of #6 , we may need to move the next material ui package back to the Next application in the meantime.
Is your feature request related to a problem? Please describe.
See existing slugs related feature in Vulcan Meteor
(slug = human readable unique id, useful for clean urls for instance for articles)
Is your feature request related to a problem? Please describe.
We currently have an API key pattern in Vulcan, see "context" creation for instance. It grants admin rights to the API user => it is only meant to be used for services owned by the same company. You can't give an API key to a partner company for example, as it lacks finer permissions.
Describe the solution you'd like
A new "apis" groups for basic permission handling?
But most importantly, clean "signup"/authentication process for server to server communication.
As a first step, we could simply reintroduce API keys into Vulcan Next/Vulcan NPM based on Vulcan Meteor current implementation.
Is your feature request related to a problem? Please describe.
2 kinds of leaks:
Describe the solution you'd like
// myModel.ts
// We could still use declarative resolvers here, like hasMany relationships, since they don't leak code
export const MyModel = createGraphqlModel({...}) // type: VulcanGraphqlModel
// myModel.server.ts
// Put field resolvers here so they are server only
interface FieldServerSchema extends VulcanSchema {
resolver: ...
}
interface VulcanGraphqlServerModel extends VulcanGraphqlModel {
...
}
export const MyModel = extendGraphqlModel({ ... }) // type: VulcanGraphqlServerModel
// index.ts
// the index would export the main model => no risk of leaking server code.
export * from "./myModel"
Then it's user responsibility to import "myModel.server" instead of "myModel" in /api/graphql
(we could provide an exemple in Vulcan next.
Main difficulty is to merge everything correctly and get the right typing everywhere to differentiate where we can accept both kind of model and where we accept only common model.
Note: we could also provide a createGraphqlServerModel
, for contexts where you want to create directly a server schema (eg in future "Vulcan Express" where you have only a server and no client).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.