Create multiple custom-elements with Svelte and Rollup in Visual Studio - visual-studio

I'm trying to create multiple web-custom elements using Svelte and Rollup inside the one project.
The idea is to have a folder structure like this
web-components
component-1
index.svelte
component-2
index.svelte
This should the be "looped" by Rollup and create a set of JS files
publish
component-1.js
component-2.js
Each of the svelte components will be standalone/autonomous, and I might also create other components using other technologies as well. (React/Vanilla.js/lit.hmtl/stencil)
I'm working in Visual Studio, and the examples for doing these things is quite sparse.. Anyone that can direct me to a good example?

I do not have a current example for what you are trying to do, but having done something similar this seems to be an approach worth trying:
Your rollup.config.js file can, instead of a single object, return an array:
export default [
{ configuration for component 1 },
{ configuration for component 2 }
];
Since each configuration would have some duplication (plugins, format, ...) it's probably best to abstract those out:
const toRollupConfig = ({ src, dest }) = {
/// Rollup Configuration
};
export default [
toRollupConfig({
src: './web-components/component-1/index.svelte',
dest: './publish/component-1.js'
}),
toRollupConfig({
src: './web-components/component-2/index.svelte',
dest: './publish/component-2.js'
}),
];
Since this would require you make a line for each component, you could go a step further and fetch all your .svelte files using something like glob or similar and map the result with toRollupConfig given you the final code:
const GetComponents = (srcDir, destDir) => {
// Get the files and return for each an object of the form { src, dest }
};
const toRollupConfig = ({ src, dest }) = {
/// Rollup Configuration
};
export default GetComponents('./web-components/','./publish').map(toRollupConfig);

Related

Use RTK Query with Graphql

So far I understand I need to build my own baseQuery. I could write graphql queries and mutations like in example here https://rtk-query-docs.netlify.app/examples/react-with-graphql, will I get full type safety for queries and mutations if I add types to query.builder like this builder.query<Device, void> or I must use something like this https://www.graphql-code-generator.com/docs/plugins/typescript-graphql-request#simple-request-middleware. In latter case how should my baseQuery look if I use generated hook for graphql-request library.
Here is example of hook from 2:
import { GraphQLClient } from 'graphql-request';
import { getSdk } from './sdk'; // THIS FILE IS THE GENERATED FILE
async function main() {
const client = new GraphQLClient('https://countries.trevorblades.com/');
const sdk = getSdk(client);
const { continents } = await sdk.continents(); // This is fully typed, based on the query
console.log(`GraphQL data:`, continents);
}
I am thinking something like:
import {getSdk} from './sdk'
const client = new GraphQLClient('https://countries.trevorblades.com/');
const graphqlBaseQuery = (someGeneratedQueryOrMutation, client) => {
const something = someGeneratedQueryOrMutation(client);
const { continents } = await something.continents();
return { data: continents };
};
Code does not really make sence but I hope you see where I am going with this. Thanks :)
Edit: By now there is a Grahql Codegen plugin available at https://www.graphql-code-generator.com/docs/plugins/typescript-rtk-query
Actually I started writing a plugin for the code generator a few days ago.
You can see the generated result here:
https://github.com/phryneas/graphql-code-generator/blob/5f9a2eefd81538782b791e0cc5df633935164a89/dev-test/githunt/types.rtk-query.ts#L406-L427
This would require you to create an api with a baseQuery using a graphql library of your choice like this.
A configuration would look like this
./dev-test/githunt/types.rtk-query.ts:
schema: ./dev-test/githunt/schema.json
documents: ./dev-test/githunt/**/*.graphql
plugins:
- typescript
- typescript-operations
- typescript-rtk-query
config:
importBaseApiFrom: '../../packages/plugins/typescript/rtk-query/tests/baseApi'
exportHooks: true
And I think for bundle-splitting purposes it would also work with the near-operation-file preset.
All that is not upstream yet - I will try to get that ready this weekend but don't know how much time it would take to actually get it in.
You could check the repo out, do a local build and install it with something like yalc though.
For a more basic approach without code generation you could look at this example or for an a bit more advanced setup (but also without full code generation, more integrated with existing tooling) you could look at this PR

Howto add a custom link provider

In the latest release of vscode (1__49), there is a code snippet on creating a new link provider. https://code.visualstudio.com/updates/v1_49. I can't seem to find a reference on where to apply this code.
window.registerTerminalLinkProvider({
provideTerminalLinks: (context, token) => {
// Detect the first instance of the word "test" if it exists and linkify it
const startIndex = (context.line as string).indexOf('test');
if (startIndex === -1) {
return [];
}
// Return an array of link results, this example only returns a single link
return [
{
startIndex,
length: 'test'.length,
tooltip: 'Show a notification',
// You can return data in this object to access inside handleTerminalLink
data: 'Example data'
}
];
},
handleTerminalLink: (link: any) => {
vscode.window.showInformationMessage(`Link activated (data = ${link.data})`);
}
});
What is the process for getting the editor to utilize this feature?
You will need to create a vscode extension that includes your code.
As it so happens, I have just set up a fresh extension that will use the TerminalLinkProvider. You can take a look at how the sample code integrates into a sample extension on GitHub.
A good place to start with your first extension is the official guide.
After that, just add your code to the activate(...) function of your extension.
You can built your extension as a .vsix file and install it in any vscode instance you use, but if you think that your code might be of value to others, consider publishing it!

Access JSON chunk exported from Gatsby Static Query

I have a React Component in a Gatsby app that is using the useStaticQuery hook to pull in data from the GraphQL layer. This component gets used in my application, but it also gets used as part of a JavaScript embed/widget that is created in a separate Webpack configuration.
I don't want the widget to depend on Gatsby, so I've shimmed the relevant bits of Gatsby, but I still need to pass in data to the shim I've created for useStaticQuery. I found that my Gatsby app is generating a file at public/static/d/2250905522.json that contains a perfect representation of the query data, and I'd like to use it like so:
// This file gets substituted when importing from `gatsby`
import queryResult from "../public/static/d/2250905522.json"
export const useStaticQuery = () => queryResult.data
export const graphql = () => {}
This works, but I haven't figured out where this is coming from or how to determine the file name in a way that is deterministic/stable. How is Gatsby determining this file name, and what internals might I use to do the same?
Edit: I found this routine in the Gatsby codebase that appears to be using staticQueryComponent.hash to determine the number. staticQueryComponent is being destructured from store.getState() where store is associated with Redux, but I'm still not sure where the hash is being determined yet.
Edit 2: Found another mention of this in the documentation here. It sounds like hash is a hash of the query itself, so this will change over time if the query changes (which is likely), so I'm still looking for the routine used to compute the hash.
Due to changes in the babel-plugin-remove-graphql-queries, coreyward's (awesome) answer should be updated to:
const { stripIgnoredCharacters } = require('graphql/utilities/stripIgnoredCharacters');
const murmurModule = require('babel-plugin-remove-graphql-queries/murmur');
const murmurhash = typeof murmurModule === 'function' ? murmurModule : murmurModule.murmurhash;
const GATSBY_HASH_SEED = 'abc';
function hashQuery(query) {
const result = murmurhash(stripIgnoredCharacters(query), GATSBY_HASH_SEED).toString();
return result;
}
module.exports = hashQuery;
The changes are:
fix the way murmurhash is imported. Credit to github user veloce, see: https://github.com/birkir/gatsby-source-graphql-universal/pull/16/files
Change to using stripIgnoredCharacters in order to match the updated way that gatsby internally hashes queries by first stripping whitespace and comment lines for efficiency.
Gatsby is using murmurhash with a seed of "abc" to calculate the hash of the full text of the query (including whitespace). This occurs in babel-plugin-remove-graphql-queries.
Since the reused components are isolated from Gatsby, the graphql tagged template literal can be shimmed in order to get the original query for hashing:
// webpack.config.js
module.exports = {
resolve: {
alias: {
gatsby: path.resolve(__dirname, "gatsby-shim.js"),
},
},
}
// gatsby-shim.js
import { murmurhash } from "babel-plugin-remove-graphql-queries/murmur"
import {
stripIgnoredCharacters,
} from "graphql/utilities/stripIgnoredCharacters"
const GATSBY_HASH_SEED = "abc"
const hashQuery = (query) =>
murmurhash(
stripIgnoredCharacters(query),
GATSBY_HASH_SEED
).toString()
export const graphql = query => hashQuery(query.raw[0])
This results in the query hash being passed into useStaticQuery, which can be shimmed similarly to retrieve the cached query from disk.
Also worth noting, newer versions of Gatsby store the StaticQuery result data in public/page-data/sq/d/[query hash].json.
If you're looking to do something similar, I've written up a much longer blog post about the details of this process and the solution I arrived at here.

Complex query variables in GraphQL (via Gatsby)

I am building a localized static website using Gatsby, with the help of gatsby-plugin-intl. This plugin adds a context variable named intl to pages (including template-based pages), which is an object: https://github.com/wiziple/gatsby-plugin-intl/blob/master/src/gatsby-node.js#L27-L34
I would like to access the intl.language variable from the context within a page query. This is my (failing) code at this stage:
query($slug: String!, $intl: String) {
contentfulPerson(slug: {eq: $slug}, node_locale: {eq: $intl.language}) {
name
}
}
Contentful is the headless CMS I use and from which I would like to fetch data in the correct locale.
Obviously this code has two problems: $intl is not a string, and $intl.language is not syntactically correct. But I don't know how to fix either problem.
I guess I could either fork the plugin or do something in my own gatsby-node.js to make the language available as a top-level variable in the context, but I'm interested to know if there is a way to do it directly.
The Gatsby docs say that query variables can be complex (https://www.gatsbyjs.org/docs/graphql-reference/#query-variables) but in the example they provide, they don't show how the types are defined or how to access a property within these variables.
EDIT : I tried moving the language to a top-level context variable in my gatsby-node.js using this code:
exports.onCreatePage = ({page, actions}) => {
const { createPage, deletePage } = actions
deletePage(page)
createPage({
...page,
context: {
...page.context,
language: page.context.intl.language
}
})
}
but the program runs out of memory (even when increasing max_old_space_size)
You can move the language field to a top-level context by doing this:
exports.onCreatePage = ({ page, actions }) => {
const { createPage, deletePage } = actions
const oldPage = Object.assign({}, page)
page.context.language = page.context.intl.language;
if (page.context.language !== oldPage.context.language) {
// Replace new page with old page
deletePage(oldPage)
createPage(page)
}
}
Checking if the field has changed avoids the infinity loop.

Using pageBase with nightwatch.js

I'm trying to create an end-2-end test suite using nightwatch.js
I've looked around a bit and haven't really figured out how to use a pageBase, like is usually used when implementing POM.
I'm using the page_object that is built in to nightwatch, but can't seem to get it to use a pageBase.
Here is the code example.
To simplify things, let's say I have a common.js file, and a test.js file
I want test.js to inherit all of common.js commands and elements and implement some commands and elements of it's own, but I'm struggling with the syntax.
this is the common.js file
let commonCommands = {
clickOnMe: function () {
return this.waitForElementVisible('#someElement', 2000)
}
};
module.exports = {
commands: [commonCommands],
elements: {
someElement: '#elementId'
},
};
this is the test.js file
const common = require('./common');
let testCommands = {
doStuffFromTest: function () {
return this;
}
};
module.exports = {
url: function () {
return this.api.launch_url ;
},
commands: common.commands,
elements: common.elements
};
How can I add commands and elements to the test.js ?
You generally don't want to access those commands from your test, but rather from your other page objects. Since that's where all of your commands will be happening, common actions like clicking on an element or checking if something is present will be done at the page object level.

Resources