GithubHelp home page GithubHelp logo

Comments (18)

james-yeoman avatar james-yeoman commented on June 6, 2024 1

Thank you. We appreciate the effort you put into this library, and want to see the best for it.

Enjoy your time off!

from bwip-js.

metafloor avatar metafloor commented on June 6, 2024

There is no default, as each module is targeted to the specific features of the platform. And it makes no sense to include a default since it will likely be wrong half the time. I agree with you that a solution to this is needed. My question is: what is tsc looking for in the exports map before it falls back to the default? It appears that it is not looking for the node and browser targets. Maybe nodenext?

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

Using --traceResolution, the Bundler module resolution only uses import and types conditions

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

It also appears that using customConditions in the app tsconfig and rendering lambda's tsconfig doesn't cascade to the renderer library. I'll go and make a bug report on the typescript repo

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

Hmm... while creating a reproduction repo for the typescript repo bug report, I realised something else: the IDE can't resolve bwip-js for the exact same reason. I'm going to consult with the rest of my team, but I'm leaving this issue open in the meantime

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

@metafloor I've made a repo to reproduce the exact problem this issue was created for. I've also detailed a bit more thoroughly about the use-case in the readme.

Also, I was wondering: what if you had the default condition resolve to a version that only had functions that have a DrawingContext parameter? That looks like the shared interface between the different platforms to me, but I may well be completely wrong there.

If people wanted to use "moduleResolution": "Bundler" and one of the helper functions, they'd need to specify the appropriate custom conditions in their tsconfig, sure. But at that point, they're much more likely to only be targeting one platform, since they'd be getting platform-specific types from those functions.

from bwip-js.

metafloor avatar metafloor commented on June 6, 2024

I am very leery of creating a default that does not match the readme. It will cause no end of grief when a bundler chooses incorrectly. I would rather the bundler fail to resolve (as with this current issue), so we can better understand where improvements can be made in package.json (see #298 for example) or in a bundler's imports resolution.

nodejs did a good job of documenting how export maps are supposed to be used. Now we just need the bundler implementations to work out the kinks using real world projects like bwip-js that provide different modules for different platforms.

I am still confused why tsc is not looking at either the browser or node targets. Don't you need to tell tsc the underlying platform it should be targeting?

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

The bundler module resolution mode makes no assumptions about the platform you're targeting. Since I use vite for building the frontend, the browser condition gets resolved. On the backend, I use esbuild, and it's targetting node.

The problem is with typechecking the library, since it doesn't have a specific platform that it targets.

I may very well be in unusual territories with my setup, but nonetheless, it's a painpoint for me that I'd like to see some way of resolving.
I'm not in unusual territories, because npx create-vite, yarn create vite, and the other similar project scaffold executables default to "moduleResolution": "Bundler".

It's something that'll become more commonplace as time goes on.

At the moment, I'm looking at using the following declaration file in order to use the platform-agnostic declarations (trimmed down to only the signatures that the renderer lib needs)

Details
// Taken from bwip-js/dist/bwip-js.d.ts and stripped down to only what we need
//
// Necessary until https://github.com/metafloor/bwip-js/issues/306 is resolved
//
// This enables Typescript and VS Code to typecheck without needing any custom
// conditions for exports map resolution.
//
// Our buildtools can resolve the exports map correctly, as they have the neccessary
// context at build time to decide which version to use (vite uses the "browser"
// condition, and @lll/api uses esbuild to bundle for node, so would use the "node"
// condition)

// I know... reaching into node_modules is a sin... it's the only way to do this
// since the `declare module` line after, masks the `bwip-js` import specifier
// globally, so I can't do `import type {...} from "bwip-js/dist/bwip-js"
import type {
	RenderOptions,
	DrawingContext
} from "../node_modules/bwip-js/dist/bwip-js";

declare module "bwip-js" {
	export namespace BwipJs {
		export type { RenderOptions, DrawingContext };

		// Can't select which overloads to import, so have to copy signatures instead
		export function code128(
			opts: RenderOptions,
			drawing: DrawingContext<Promise<T>>
		): Promise<T>;
		export function code128(
			opts: RenderOptions,
			drawing: DrawingContext<T>
		): T;
		export function ean13(
			opts: RenderOptions,
			drawing: DrawingContext<Promise<T>>
		): Promise<T>;
		export function ean13(
			opts: RenderOptions,
			drawing: DrawingContext<T>
		): T;
		export function ean8(
			opts: RenderOptions,
			drawing: DrawingContext<Promise<T>>
		): Promise<T>;
		export function ean8(
			opts: RenderOptions,
			drawing: DrawingContext<T>
		): T;
		export function gs1_128(
			opts: RenderOptions,
			drawing: DrawingContext<Promise<T>>
		): Promise<T>;
		export function gs1_128(
			opts: RenderOptions,
			drawing: DrawingContext<T>
		): T;
		export function itf14(
			opts: RenderOptions,
			drawing: DrawingContext<Promise<T>>
		): Promise<T>;
		export function itf14(
			opts: RenderOptions,
			drawing: DrawingContext<T>
		): T;
		export function qrcode(
			opts: RenderOptions,
			drawing: DrawingContext<Promise<T>>
		): Promise<T>;
		export function qrcode(
			opts: RenderOptions,
			drawing: DrawingContext<T>
		): T;
		export function upca(
			opts: RenderOptions,
			drawing: DrawingContext<Promise<T>>
		): Promise<T>;
		export function upca(
			opts: RenderOptions,
			drawing: DrawingContext<T>
		): T;
	}

	export = BwipJs;
}

and so far, the results seem promising. Typechecking is successful in the frontend, backend, and the renderer library.

Now to test that it builds correctly

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

It indeed builds correctly.

Since customConditions will allow people to specify their build platform, we come back to the scenario of "I'm using this in a kind-of non-standard way, how can we solve this so people don't have problems in the future".

What if you used subpath mapping to have bwip-js/web, bwip-js/node, etc, and then have a bwip-js/context-only that resembles my declaration file in the above comment?

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

In fact, how about having the core resemble my declaration file (only expose functions with drawing contexts as params), and then have separate DrawingContexts for web and node?

That would likely allow you to remove the platform-specific dependencies for the core api, and still support multiple platforms.

If anything, it'd make it easier to support new platforms in the future, as you'd only need to implement a new DrawingContext

from bwip-js.

metafloor avatar metafloor commented on June 6, 2024

I am not thrilled with this idea as it fails to support the generic methods like toBuffer() and toCanvas() which are heavily used by most of the users. My current thinking is to provide import paths that target a specific platform. For example import { ... } from "bwip-js/browser" or import bwipjs from "bwip-js/node". Inside those export map entries would be the platform specific type definitions. And the current export map would be re-homed to the . path, which should maintain backward compatibility.

The problem is I have no way of knowing if it will work. I can test against the usual bundlers, but I don't use typescript or vs code and am not willing to go down that rabbit hole.

And the solution must maintain backward compatibility with non-typescript users.

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

That sounds like a decent compromise, but the point still stands that I have a case where I don't need the toBuffer or toCanvas methods, and would prefer a platform-agnostic solution.

Would it be possible to do as you've outlined, while also providing a bwip-js/context-only or bwip-js/drawing-context path that excludes all platform-specific methods? This wouldn't necessarily need to be backwards-compatible, so could exist as just a path mapping entry

from bwip-js.

metafloor avatar metafloor commented on June 6, 2024

Why would you need a module that does not include the generic methods? That makes no sense. This solution is already platform-specific and your bundler-of-choice will tree-shake the module to only include what is used by your code.

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

Because my team has a platform-agnostic rendering system that we hook bwip-js up to, using DrawingContext, in order to render barcodes on all the platforms we have.

We don't make use of toCanvas and toBuffer. We exclusively use the DrawingContext signatures
(i.e. export function ean8(opts: RenderOptions, drawing: DrawingContext<T>): T;) and implement DrawingContext for each of our platforms.

from bwip-js.

metafloor avatar metafloor commented on June 6, 2024

Alright, so I will add a generic target as well, but it won't happen right away. I am on holiday for the next two weeks and will expect the usual chaos the week after I return....

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

@metafloor I see you've not been able to hit the self-imposed deadline you mentioned in 310. Is there anything I can do to help?

from bwip-js.

metafloor avatar metafloor commented on June 6, 2024

v4.1.2 provides enumerated platform targets in package.json. The readme has not been updated because I want to ensure this is working without breaking backward compatibility. Hopefully not too much screaming will result....

The previous exports map has been moved to the . target and the following explicit targets have been added:

./browser
./node
./electron
./react-native
./generic

To import just the cross-platform code, you would use:

import { toSVG, qrcode } from 'bwip-js/generic';

Please let me know if that works for your use case.

from bwip-js.

james-yeoman avatar james-yeoman commented on June 6, 2024

Yes, this works perfectly for me! Thank you!

from bwip-js.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.