rdfjs / N3.js

Lightning fast, spec-compatible, streaming RDF for JavaScript
http://rdf.js.org/N3.js/
Other
715 stars 132 forks source link

Import not found in `N3Lexer.js` causes `n3` to fail in Web Component #297

Open vemonet opened 2 years ago

vemonet commented 2 years ago

Hi, @jeswr @RubenVerborgh I am trying to use n3 in a Web Component built using Lit Element, so in-browser javascript, but there seems to be issues with n3 imports (which also impacts using rdflib.js)

I am trying to run the basic example provided by the docs after installing with yarn add n3 in a Web Component contructor():

import {LitElement, html, css} from 'lit';
import {customElement, property} from 'lit/decorators.js';
import N3 from 'n3';

@customElement('my-element')
export class MyElement extends LitElement {
  static override styles = css`
    :host {
      display: block;
      border: solid 1px gray;
      padding: 16px;
      max-width: 800px;
    }
  `;

  @property({type: Object})
  value = {};

  constructor() {
    super();

    console.log("In constructor")

    const { DataFactory } = N3;
    const { namedNode, literal, defaultGraph, quad } = DataFactory;
    const myQuad = quad(
      namedNode('https://ruben.verborgh.org/profile/#me'),
      namedNode('http://xmlns.com/foaf/0.1/givenName'),
      literal('Ruben', 'en'),
      defaultGraph(),
    );
    console.log(myQuad.termType);              // Quad
    console.log(myQuad.value);                 // ''
    console.log(myQuad.subject.value);         // https://ruben.verborgh.org/profile/#me
    console.log(myQuad.object.value);          // Ruben
    console.log(myQuad.object.datatype.value); // http://www.w3.org/1999/02/22-rdf-syntax-ns#langString
    console.log(myQuad.object.language);       // en
  }

  override render() {
    return html`
      <h1>Check the console logs</h1>
      <slot></slot>
    `;
  }

}

declare global {
  interface HTMLElementTagNameMap {
    'my-element': MyElement;
  }
}

fyi: I used https://github.com/lit/lit-element-starter-ts to get started with building the Web Component

I am getting this error in the console when importing n3 (also happens when working with rdflib):

Uncaught SyntaxError: import not found: default          N3Lexer.js:3:7

Note that removing all lines related to n3 apart from the import will fix the component and it will work

The problematic line in N3Lexer.js is the last one with queue-microtask

// **N3Lexer** tokenizes N3 documents.
import namespaces from './IRIs.js';
import queueMicrotask from './../../queue-microtask/index.js';

Just in case, I tried to solve it with:

yarn add queue-microtask

And I can find an index.js in the node_modules/queue-microtask but I am still getting the import not found error in the console

The here are the dependencies and their versions used in my package.json:

  "dependencies": {
    "lit": "^2.1.0",
    "n3": "^1.16.2",
    "rdflib": "^2.2.19"
  },

Do you have any idea why I am getting this error? Is it an issue on n3 side or something related to the Web Component design?

Note that currently I am just trying to parse a RDF string (e.g. turtle) to an object I can search in (with the usual .get(undefined, undefined, undefined) functions for example or SPARQL). But every solution I found out there for JS was failing (mostly because they were relying of n3 for parsing turtle I think)

I am also open if you have any suggestions of better libraries/approach to do this in the browser! :)

RubenVerborgh commented 2 years ago

import N3 from 'n3';

This is weird, I expect

import { DataFactory } from 'n3';

vemonet commented 2 years ago

I imported it this way to follow as closely as possible the example given in the readme, if I directly import DataFactory with import { DataFactory } from 'n3'; I am getting the same error in the console:

Uncaught SyntaxError: import not found: default               N3Lexer.js:3:7
vemonet commented 2 years ago

It seems to be due to the queueMicrotask import:

import queueMicrotask from './../../queue-microtask/index.js';

Currently this index.js is:

/*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
let promise

module.exports = typeof queueMicrotask === 'function'
  ? queueMicrotask.bind(typeof window !== 'undefined' ? window : global)
  // reuse resolved promise, and allocate it lazily
  : cb => (promise || (promise = Promise.resolve()))
    .then(cb)
    .catch(err => setTimeout(() => { throw err }, 0))

But it should be converted to an ES module, something like this:

/*! queue-microtask. MIT License. Feross Aboukhadijeh <https://feross.org/opensource> */
let promise

export default typeof queueMicrotask === 'function'
  ? queueMicrotask.bind(typeof window !== 'undefined' ? window : global)
  // reuse resolved promise, and allocate it lazily
  : cb => (promise || (promise = Promise.resolve()))
    .then(cb)
    .catch(err => setTimeout(() => { throw err }, 0))

There is a pull request about this actually: https://github.com/feross/queue-microtask/pull/19 but no response

RubenVerborgh commented 2 years ago

Yeah, queue-microtask needs to fix their stuff, or you could adjust your packer/environment configuration.

But it seems that queueMicrotask is now widely supported; we could drop Node 10 and take it from there.

juliusstoerrle commented 2 years ago

I agree, the queueMicrotasks import also creates issues when trying to use N3 in a web worker. (since this line throws queueMicrotask.bind(typeof window !== 'undefined' ? window : global))