Implement new syntax for importing values from JavaScript modules

New syntax for importing values from JavaScript
Motivation
Writing bindings to JavaScript has always been perceived as a rather daunting task. Most developers are not used to writing externals. If you look at TypeScript there's either something available on npm or you Any your way through the world. In ReScript it takes some practise to bring a library from npm at your fingertips. You have to learn to write an external and navigate through a sea of attributes. The team created the ReScript syntax with a very specific vision in mind. We want a familiar, yet expressive language. Struggling with JS bindings is not a part of this. Is there a way to make the life of our developers easier when it comes to importing values from JavaScript?
Basic example
// import values from a JavaScript module
import { delimiter: string } from "path"

Detailed design
Bindings to JavaScript values are currently done through a syntax based on the external keyword. Since it is a syntax for bringing in or importing JavaScript values, we move towards the import keyword. import is a known keyword in many languages: JavaScript, TypeScript, Java, Go, Swift, Haskell. The syntax for js imports will be available in both structures and signatures.
To increase familiarity for our developers, we can map the entire JavaScript import declaration syntax onto ReScript. This will greatly reduce friction for developers with a JS background. The one big difference is that ReScript import declarations require type annotations.
import { delimiter: string } from "path" // import named export from JS
import school: string from "school" // import default export JS
import  * as leftPad: (string, int) => string from "leftPad" // namespaced import, import entire module's content

Cases
Import a single export from a module
import { dirname: string => string } from "path"

// old external
@module("path")
external dirname: string => string = "dirname"

Import multiple exports from a module
import {
  delimiter: string,
  dirname: string => string,
  relative: (~from: string, ~to_: string) => string
} from "path"

// old external
@module("path")
external delimiter: string = "delimiter"
@module("path")
external dirname: (string, string) => string = "dirname"
@module("path")
external relative: (~from: string, ~to_: string) => string = "relative"

Import an export with a more convenient alias
import {renameSync as rename: (string, string) => string} from "fs"

// old external
@module("fs")
external rename: (string, string) => string = "renameSync"

import an export with an illegal ReScript identifier
import {"Fragment" as make: component<{"children": element}>} from "react"

// old external
@module("react")
external make: component<{"children": element}> = "Fragment"

import an export with additional attributes
import {
  @splice
  join: array<string> => string
} from "path"

// old external
@module("path") @splice
external join: array<string> => string = "join"

Rename multiple exports during import
import {
  renameSync as rename: (string, string) => string,
  unlinkSync as unlink: string => unit,
} from "fs"

// old external
@bs.module("path")
external rename: (string, string) => string = "renameSync"
@bs.module("path")
external unlink: string => unit = "unlinkSync"

import an entire module's contents (aka NameSpacedImport)
import * as leftPad: (string, int) => string from "leftPad"

// old external
@module
external leftPad: (string, int) => string = "leftPad"

Importing default export
import schoolName: string from "/modules/school.js";
// syntactic sugar for
import {default as schoolName: string} from "/modules/school.js";

// old external
@module("/modules/school.js") external schoolName: string = "default"

Importing default export with illegal ReScript identifier
import "SchoolName": string from "/modules/school.js";
// syntactic sugar for
import {default as "SchoolName": string} from "/modules/school.js";

// old external
@module("/modules/school.js") external schoolName: string = "default"

importing default export with named imports
import schoolName: string, {getGrade: student => int} from "/modules/school.js";

// old external
@module("/modules/school.js") external schoolName: string = "default"
@module("/modules/school.js") external getGrade: student => int = "getGrade"

importing default export with multiple named imports
import
  schoolName: string,
  {
    getGrade: student => int,
    getTeachers: unit => array<teacher>
  }
from "/modules/school.js";

// old external
@module("/modules/school.js") external schoolName: string = "default"
@module("/modules/school.js") external getGrade: student => int = "getGrade"
@module("/modules/school.js") external getTeachers: unit => array<teacher> = "getTeachers"

importing default export with namespacedimport
import schoolName: string, * as school from "/modules/school";

// old external
@module("/modules/school.js") external schoolName: string = "default"
@module external school: student => int = "/modules/school.js"

import values from JavaScript modules with @as and polyvariants
import {
  openSync: (
    path,
    @bs.string [
      | @bs.as("r") #Read
      | @bs.as("r+") #Read_write
      | @bs.as("rs+") #Read_write_sync
      | @bs.as("w") #Write
      | @bs.as("wx") #Write_fail_if_exists
      | @bs.as("w+") #Write_read
      | @bs.as("wx+") #Write_read_fail_if_exists
      | @bs.as("a") #Append
      | @bs.as("ax") #Append_fail_if_exists
      | @bs.as("a+") #Append_read
      | @bs.as("ax+") #Append_read_fail_if_exists
    ],
  ) => unit
} from "fs"

// old external
@module("fs")
external openSync: (
  path,
  @bs.string
  [
    | @bs.as("r") #Read
    | @bs.as("r+") #Read_write
    | @bs.as("rs+") #Read_write_sync
    | @bs.as("w") #Write
    | @bs.as("wx") #Write_fail_if_exists
    | @bs.as("w+") #Write_read
    | @bs.as("wx+") #Write_read_fail_if_exists
    | @bs.as("a") #Append
    | @bs.as("ax") #Append_fail_if_exists
    | @bs.as("a+") #Append_read
    | @bs.as("ax+") #Append_read_fail_if_exists
  ],
) => unit = "openSync"

import a react component from a module
import {
  @react.component
  "Circle" as make: (
    ~center: Leaflet.point,
    ~radius: int,
    ~opacity: float,
    ~stroke: bool,
    ~color: string,
    ~children: React.element=?
  ) => React.element
} from "react-leaflet"

Drawbacks

import will become a reserved keyword
Newcomers unfamiliar with ReScript's module system, might try to import generated JavaScript from the compiler. Behind the scenes you would be writing an external, pointing to the generated JavaScript.

Plan for adoption
The way we teach this is very simple:

The printer will reformat code into the new syntax where possible.
Ship a new version of the docs. Aligning the docs with a new release of the compiler containing this syntax will be crucial.

Will imported values be public members of the module, as they currently are with the external mechanism?

This certainly does seem more ergonomic / familiar to me from the JS perspective. Perhaps this is just an oversight but I don't see an example of binding to variadic functions, common practice being binding to the same function with a different name for each kind of call. I assume this would be covered though like this?
type options

import {
  rmdirSync as rmdir: (string) => unit,
  rmdirSync as rmdirWith: (string, options) => string,
} from "fs"

Newcomers unfamiliar with ReScript's module system, might try to import generated JavaScript from the compiler. Behind the scenes you would be writing an external, pointing to the generated JavaScript.

Honestly this seems like a big deal -- I can easily see users new to ReScript not understanding why some things need to be imported but not others.
Also as noted making import a keyword would break (albeit trivially) anyone who bound to module.import for code-splitting? Are there concerns here for potential overlap with syntax-level future dynamic import support?

Will imported values be public members of the module, as they currently are with the external mechanism?

Import is just syntax sugar for external, and one will format to the other, so the answer can only be yes 🤔

I feel really mixed about that one to be honest 😕
While I do agree that the external system can be confusing for newcomers, from my experience it's not because of the wording external/import but the binding system itself.
It seems the new import is basically sugar for external, but the way import works in JS and external works in ReScript are conceptually different. This will open the door to a bunch of new questions, especially since when importing/binding a value ReScript doesn't always import it right away in the generated JS file, but on call site (for functions).
Plus, as of today, there is no import/export mechanics in ReScript at all making the new syntax potentially confusing for some people who already use the language.
Additionally to the above, what about the export keyword that's basically sugar for gentype? After that pr is merged import and export are not stricly symetric 😕
When speaking with people coming from JS/TS it seems the main issue is not the wording external/import or whatever, but to grasp the whole binding system, that doesn't exist in JS and works differently in TS (there is also a confusion ReScript module / Node module for some developers).
The binding logic exists in TS where you have a different extension (.d.ts), and the declare  keyword for types for instance (Scala.js solves this with facade files as well).

I feel really mixed about that one to be honest 😕
While I do agree that the external system can be confusing for newcomers, from my experience it's not because of the wording external/import but the binding system itself.
It seems the new import is basically sugar for external, but the way import works in JS and external works in ReScript are conceptually different. This will open the door to a bunch of new questions, especially since when importing/binding a value ReScript doesn't always import it right away in the generated JS file, but on call site (for functions).
Plus, as of today, there is no import/export mechanics in ReScript at all making the new syntax potentially confusing for some people who already use the language.
Additionally to the above, what about the export keyword that's basically sugar for gentype? After that pr is merged import and export are not stricly symetric 😕
When speaking with people coming from JS/TS it seems the main issue is not the wording external/import or whatever, but to grasp the whole binding system, that doesn't exist in JS and works differently in TS (there is also a confusion ReScript module / Node module for some developers).
The binding logic exists in TS where you have a different extension (.d.ts), and the declare  keyword for types for instance (Scala.js solves this with facade files as well).

That's a much wider point than just commenting on the syntax change, and this is the wrong place for it. I suggest you post to the forum where it can be discussed properly 👍

That's a much wider point than just commenting on the syntax change, and this is the wrong place for it. I suggest you post to the forum where it can be discussed properly 👍

I don't think that's a "much wider point", this pr introduces a new syntax that i don't remember seing discussed much on the forum apart from a vague "we might introduce an import syntax" thrown in a blog post that didn't bring much details. And that syntax is meant to address the whole binding "issue".
Next step is a (very well explained) pr. There is no official annoucement or post yet on the forum, and my experience with ReasonMl/ReScript as an early adopter tells me that's better to be safe than sorry and raise concerns as soon as possible.
That being said, I'd be very happy to share my concerns on the forum if and when the core team is ready to open a post 😄

I don't think that's a "much wider point", this pr introduces a new syntax that i don't remember seing discussed much on the forum apart from a vague "we might introduce an import syntax" thrown in a blog post that didn't bring much details. And that syntax is meant to address the whole binding "issue".
Next step is a (very well explained) pr. There is no official annoucement or post yet on the forum, and my experience with ReasonMl/ReScript as an early adopter tells me that's better to be safe than sorry and raise concerns as soon as possible.
That being said, I'd be very happy to share my concerns on the forum if and when the core team is ready to open a post 😄

From my reading of the blog post it's not intended to address the entire binding issue, only provide a more friendly syntax for certain scenarios (anything that doesn't involve @module will still use external syntax).
Regardless, this is definitely the wrong place to discuss general binding issues like the difference between JS import and ReScript export; that's why I suggested making a dedicated post about it.

From my reading of the blog post it's not intended to address the entire binding issue, only provide a more friendly syntax for certain scenarios (anything that doesn't involve @module will still use external syntax).
Regardless, this is definitely the wrong place to discuss general binding issues like the difference between JS import and ReScript export; that's why I suggested making a dedicated post about it.

From my reading of the blog post it's not intended to address the entire binding issue

From my reading, it does. And that's exactly why i'm concerned: the situation, again, is not clear. What's the plan? Why a new syntax? What does it try to address if not the binding issue (with Node modules/JS files)? Why an other "breaking change" ? What about the non module bindings ? If we keep external, why bother with import instead of improving the existing syntax for modules?
As for export there is already a post, and the feature seems to be confusing for some (which justifies my concerns).
Man, ReScript really feels more and more like Elm to me....

From my reading of the blog post it's not intended to address the entire binding issue

From my reading, it does. And that's exactly why i'm concerned: the situation, again, is not clear. What's the plan? Why a new syntax? What does it try to address if not the binding issue (with Node modules/JS files)? Why an other "breaking change" ? What about the non module bindings ? If we keep external, why bother with import instead of improving the existing syntax for modules?
As for export there is already a post, and the feature seems to be confusing for some (which justifies my concerns).
Man, ReScript really feels more and more like Elm to me....

I would like to echo gaku-sei's sentiments.
I would also love to see an example of syntax for a .resi file. Some of my biggest hurdles have been trying to find out how to replicate the output of a PPX in a .resi file.
For example in the following example, what would an interface (.resi) file look like to only make renameSync visible outside of the module?
import {
  renameSync as rename: (string, string) => string,
  unlinkSync as unlink: string => unit,
} from "fs"

Finally my initial impression of the new syntax was that it makes the message of explaining ReScripts (OCaml's) module system a lot more difficult. If this syntax existed when I started learning Reason/ReScript, my first attempt would be to try and import something from another .res file just as I would in JavaScript.

I would like to echo gaku-sei's sentiments.
I would also love to see an example of syntax for a .resi file. Some of my biggest hurdles have been trying to find out how to replicate the output of a PPX in a .resi file.
For example in the following example, what would an interface (.resi) file look like to only make renameSync visible outside of the module?
import {
  renameSync as rename: (string, string) => string,
  unlinkSync as unlink: string => unit,
} from "fs"

Finally my initial impression of the new syntax was that it makes the message of explaining ReScripts (OCaml's) module system a lot more difficult. If this syntax existed when I started learning Reason/ReScript, my first attempt would be to try and import something from another .res file just as I would in JavaScript.

Just spitballing here, what if import of a rescript/reasonml/ocaml file was just an alias for open?

Just spitballing here, what if import of a rescript/reasonml/ocaml file was just an alias for open?

@yawaramin

Will imported values be public members of the module, as they currently are with the external mechanism?

Yes, public. It parses as external ….
@illusionalsagacity

I don't see an example of binding to variadic functions

You would import variadic functions with the @variadic attribute: https://rescript-lang.org/docs/manual/latest/bind-to-js-function#variadic-function-arguments. Added the example to the cases.
import {@variadic join: array<string> => string} from "path"

as noted making import a keyword would break anyone

It wouldn't break anyone. You can use keywords as regular identifiers: https://rescript-lang.org/docs/manual/latest/use-illegal-identifier-names
let \"import" = 3.14

Are there concerns here for potential overlap with syntax-level future dynamic import support?

This is an excellent question. There's still room in the syntax for import('/modules/my-module.js'). This can be made explicitly available when needed.

what if import of a rescript/reasonml/ocaml file was just an alias for open / let assignments?

The purpose of import is to import values from JavaScript. Unlike JavaScript, ReScript doesn't have or need import statements.
@KingDutch

what would an interface (.resi) file look like

There would be no magic here, and you would do business as usual: (Added as example to the cases)
// Path.resi
import { delimiter: string } from "path"

@gaku-sei @KingDutch, I hear you loud and clear. We want ReScript users to ship products, starting from a basic web app to a fully integrated SaaS solution built on JavaScript. Anything that we can do to help our developers ship, we will. Exploring new syntax to seamlessly interop between ReScript and JavaScript is one area where we can innovate and provide significant value for ReScript developers. This draft PR is a first step towards that vision. Regarding non module bindings, more research is needed and is high on my list. We definitely don't want to make things more difficult. One benefit of the new syntax parser is that it has been engineered with error messages in mind. So instead of <syntax error> we can actually link to good documentation and explain what went wrong. Importing ReScript from ReScript, is one example where we can show a nice error message and link to the docs. I am working closely with @ryyppy. We will document everything in detail.
Happy to answer more questions and best wishes for the new year!

@yawaramin

Will imported values be public members of the module, as they currently are with the external mechanism?

Yes, public. It parses as external ….
@illusionalsagacity

I don't see an example of binding to variadic functions

You would import variadic functions with the @variadic attribute: https://rescript-lang.org/docs/manual/latest/bind-to-js-function#variadic-function-arguments. Added the example to the cases.
import {@variadic join: array<string> => string} from "path"

as noted making import a keyword would break anyone

It wouldn't break anyone. You can use keywords as regular identifiers: https://rescript-lang.org/docs/manual/latest/use-illegal-identifier-names
let \"import" = 3.14

Are there concerns here for potential overlap with syntax-level future dynamic import support?

This is an excellent question. There's still room in the syntax for import('/modules/my-module.js'). This can be made explicitly available when needed.

what if import of a rescript/reasonml/ocaml file was just an alias for open / let assignments?

The purpose of import is to import values from JavaScript. Unlike JavaScript, ReScript doesn't have or need import statements.
@KingDutch

what would an interface (.resi) file look like

There would be no magic here, and you would do business as usual: (Added as example to the cases)
// Path.resi
import { delimiter: string } from "path"

@gaku-sei @KingDutch, I hear you loud and clear. We want ReScript users to ship products, starting from a basic web app to a fully integrated SaaS solution built on JavaScript. Anything that we can do to help our developers ship, we will. Exploring new syntax to seamlessly interop between ReScript and JavaScript is one area where we can innovate and provide significant value for ReScript developers. This draft PR is a first step towards that vision. Regarding non module bindings, more research is needed and is high on my list. We definitely don't want to make things more difficult. One benefit of the new syntax parser is that it has been engineered with error messages in mind. So instead of <syntax error> we can actually link to good documentation and explain what went wrong. Importing ReScript from ReScript, is one example where we can show a nice error message and link to the docs. I am working closely with @ryyppy. We will document everything in detail.
Happy to answer more questions and best wishes for the new year!

@IwanKaramazow thank you. This is meaningfully different from the behaviour of ES's import statement, which brings the identifiers into scope only in the module and does not re-export them publicly. What do you think of instead using the export keyword? Both ES and TS use export to declare things that should be exported from the module. It would avoid the confusion of how it works and bypass any potential issues with people trying to import from ReScript sources.

@IwanKaramazow thank you. This is meaningfully different from the behaviour of ES's import statement, which brings the identifiers into scope only in the module and does not re-export them publicly. What do you think of instead using the export keyword? Both ES and TS use export to declare things that should be exported from the module. It would avoid the confusion of how it works and bypass any potential issues with people trying to import from ReScript sources.

@Kingdutch yes, there may be an initial learning curve for mistaking import for ReScript module imports... on the other hand, ppl will very quickly hit some walls (either don't know how what file to import, or they will realize that they need to add types to their imports, which will feel wrong). We'll have proper error messages, and hopefully, ppl will also read the (import / export](https://rescript-lang.org/docs/manual/latest/import-export) at some point? 😅
advantage of this particular syntax is that it is extremely easy to type and remember. Alternative would be to do @js import ...., which is gettin rather annoying after learning the differences?

@Kingdutch yes, there may be an initial learning curve for mistaking import for ReScript module imports... on the other hand, ppl will very quickly hit some walls (either don't know how what file to import, or they will realize that they need to add types to their imports, which will feel wrong). We'll have proper error messages, and hopefully, ppl will also read the (import / export](https://rescript-lang.org/docs/manual/latest/import-export) at some point? 😅
advantage of this particular syntax is that it is extremely easy to type and remember. Alternative would be to do @js import ...., which is gettin rather annoying after learning the differences?

@yawaramin if I'm reading this correct, you're proposing export {dirname: string => string, delimiter: string} from "path" to import values from JavaScript?

@yawaramin if I'm reading this correct, you're proposing export {dirname: string => string, delimiter: string} from "path" to import values from JavaScript?

Thanks for all the additional details. I think there may be a philosophical reason why it doesn’t quite sit right with me. I’ll try to explain.
I like ReScript (and formerly ReasonML/BuckleScript) because it doesn’t try to mix into JavaScript. TypeScript does blur the line with all sorts of annoyances as a result. Instead ReScript is a separate language. The boundaries are clearly defined and afterwards I can stop thinking about them.
This line between ReScript and JavaScript is clearly demarcated by the word “external”. I’m binding to something outside of ReScript. After that binding, I can stop thinking about it. From what I’ve seen in my own projects thus encourages putting bindings in specific modules or packages and then not thinking about the JavaScript part.
What I am worried about with the new syntax is that this line is blurred and people are encouraged to start importing things all over the place. This works fine in the relatively simplistic examples given above but can cause major problems when multiple types of a module need to be passed around and start working together. Encouraging new people to use import instead of a module encapsulating external can cause duplicate incompatible type definitions throughout the codebase.
In summary I don’t feel like the syntactic sugar is enough of an improvement over the existing tools to warrant blurring the lines of separation of concern that are a great power in ReScript.

The printer will reformat code into the new syntax where possible.

Perhaps allowing people to disable this could alleviate.
A complete alternative could be to make the import syntax a doc tool only. Write the code that transforms a valid JS import statement into an external declaration. Add that as a tool to the docs and people can copy and paste the output into their project.
————-
There are two other considerations that I have: import overloading in JavaScript and FFI to non-js code.
To the first point: In JavaScript we see that modern platforms allow importing all sorts of things, like CSS, Images, etc. Will we support those things as well with the new syntax? How will the errors look for users when they try to import an image as a URL? Are we leaving ourselves room to add this in the future?
To the second point: one of the beautiful things for me, when I started out learning Reason, is that external just points to some external resource and the compiler figures out how to interop based on the context. In BuckleScript, annotations would make that an external to JS. In OCaml it could be to any other language.
This provides an interesting extension point because with the right PPX this could be extended to other external resources such as WASM or TypeScript.

Thanks for all the additional details. I think there may be a philosophical reason why it doesn’t quite sit right with me. I’ll try to explain.
I like ReScript (and formerly ReasonML/BuckleScript) because it doesn’t try to mix into JavaScript. TypeScript does blur the line with all sorts of annoyances as a result. Instead ReScript is a separate language. The boundaries are clearly defined and afterwards I can stop thinking about them.
This line between ReScript and JavaScript is clearly demarcated by the word “external”. I’m binding to something outside of ReScript. After that binding, I can stop thinking about it. From what I’ve seen in my own projects thus encourages putting bindings in specific modules or packages and then not thinking about the JavaScript part.
What I am worried about with the new syntax is that this line is blurred and people are encouraged to start importing things all over the place. This works fine in the relatively simplistic examples given above but can cause major problems when multiple types of a module need to be passed around and start working together. Encouraging new people to use import instead of a module encapsulating external can cause duplicate incompatible type definitions throughout the codebase.
In summary I don’t feel like the syntactic sugar is enough of an improvement over the existing tools to warrant blurring the lines of separation of concern that are a great power in ReScript.

The printer will reformat code into the new syntax where possible.

Perhaps allowing people to disable this could alleviate.
A complete alternative could be to make the import syntax a doc tool only. Write the code that transforms a valid JS import statement into an external declaration. Add that as a tool to the docs and people can copy and paste the output into their project.
————-
There are two other considerations that I have: import overloading in JavaScript and FFI to non-js code.
To the first point: In JavaScript we see that modern platforms allow importing all sorts of things, like CSS, Images, etc. Will we support those things as well with the new syntax? How will the errors look for users when they try to import an image as a URL? Are we leaving ourselves room to add this in the future?
To the second point: one of the beautiful things for me, when I started out learning Reason, is that external just points to some external resource and the compiler figures out how to interop based on the context. In BuckleScript, annotations would make that an external to JS. In OCaml it could be to any other language.
This provides an interesting extension point because with the right PPX this could be extended to other external resources such as WASM or TypeScript.

@Kingdutch

I like ReScript (and formerly ReasonML/BuckleScript) because it doesn’t try to mix into JavaScript.

I'd state the exact opposite though... ReScript's success stems from the fact that we can seamlessly interact with JS without introducing a huge runtime / serialization layer. It would be really great to have the right language constructs to express zero-cost bindings and to allow quick JS interactions though.

What I am worried about with the new syntax is that this line is blurred and people are encouraged to start importing things all over the place.

It's more of a question why users import things all over the place (something that is already happening today btw, this is not related to simpler syntax).
I guess nobody imports stuff for fun, but more due to the fact that they cannot find any pure ReScript equivalents to library X, or they need to interact with their existing codebase (which will be very very likely). They probably also often need to interact with global apis such as the WebAPI, and currently it's terribly inefficient to write, read and teach those external bindings.
I think it's not less obvious that we are using unsafe code than with the external keyword, because we'll need to provide types for each import.. Some users might think we'll do some wrapping magic, but after they run into their first external related runtime error, or inspect the JS output (something we always adviced to this day), they will understand that we don't make it type-safe for them.

This line between ReScript and JavaScript is clearly demarcated by the word “external”.

Spotting the line shouldn't be harder than with externals. If I'd want to assess the amount of unsafe interop happening in my codebase, I'd regex search for the import keyword, just in the same way as with external. It's not like we are introducing an any type.. nothing has changed from a type safety perspective.
I'd be more worried about users advertising Obj.magic though 😄

This works fine in the relatively simplistic examples given above but can cause major problems when multiple types of a module need to be passed around and start working together. Encouraging new people to use import instead of a module encapsulating external can cause duplicate incompatible type definitions throughout the codebase.

Not sure how this is related to import in general? If I'd realize that one of my modules is reliant on type x that is introduced by via externals multiple times in different modules, I'd probably factor that out in a separate module, no? E.g. you could introduce a type Canvas.t and use it between different modules using import to interact with the Canvas api?

To the first point: In JavaScript we see that modern platforms allow importing all sorts of things, like CSS, Images, etc. Will we support those things as well with the new syntax?

Sure (as long as you configured your JS loader correctly):
import userImg: string from "/public/static/userImg"

// desugars to
@module("/public/static/userImg.jpg") external userImg: unit = "default"

How will the errors look for users when they try to import an image as a URL? Are we leaving ourselves room to add this in the future?

The syntax literally desugars to @module externals, so the import doesn't do any specific logic (therefore you can use urls or whatever you please, as long as you use the es6 output), and your JS loader is responsible for showing the right error if a user tries to import invalid resources.
@IwanKaramazow sticked with the ES6 import conventions, so I am pretty sure we are future proof.

To the second point: one of the beautiful things for me, when I started out learning Reason, is that external just points to some external resource and the compiler figures out how to interop based on the context. In BuckleScript, annotations would make that an external to JS. In OCaml it could be to any other language.

The external keyword will still exist, and the import syntax is just "an alias" to the right external decorations (@module). All the beauty will still persist, and there is no change in the compiler preventing that.

@Kingdutch

I like ReScript (and formerly ReasonML/BuckleScript) because it doesn’t try to mix into JavaScript.

I'd state the exact opposite though... ReScript's success stems from the fact that we can seamlessly interact with JS without introducing a huge runtime / serialization layer. It would be really great to have the right language constructs to express zero-cost bindings and to allow quick JS interactions though.

What I am worried about with the new syntax is that this line is blurred and people are encouraged to start importing things all over the place.

It's more of a question why users import things all over the place (something that is already happening today btw, this is not related to simpler syntax).
I guess nobody imports stuff for fun, but more due to the fact that they cannot find any pure ReScript equivalents to library X, or they need to interact with their existing codebase (which will be very very likely). They probably also often need to interact with global apis such as the WebAPI, and currently it's terribly inefficient to write, read and teach those external bindings.
I think it's not less obvious that we are using unsafe code than with the external keyword, because we'll need to provide types for each import.. Some users might think we'll do some wrapping magic, but after they run into their first external related runtime error, or inspect the JS output (something we always adviced to this day), they will understand that we don't make it type-safe for them.

This line between ReScript and JavaScript is clearly demarcated by the word “external”.

Spotting the line shouldn't be harder than with externals. If I'd want to assess the amount of unsafe interop happening in my codebase, I'd regex search for the import keyword, just in the same way as with external. It's not like we are introducing an any type.. nothing has changed from a type safety perspective.
I'd be more worried about users advertising Obj.magic though 😄

This works fine in the relatively simplistic examples given above but can cause major problems when multiple types of a module need to be passed around and start working together. Encouraging new people to use import instead of a module encapsulating external can cause duplicate incompatible type definitions throughout the codebase.

Not sure how this is related to import in general? If I'd realize that one of my modules is reliant on type x that is introduced by via externals multiple times in different modules, I'd probably factor that out in a separate module, no? E.g. you could introduce a type Canvas.t and use it between different modules using import to interact with the Canvas api?

To the first point: In JavaScript we see that modern platforms allow importing all sorts of things, like CSS, Images, etc. Will we support those things as well with the new syntax?

Sure (as long as you configured your JS loader correctly):
import userImg: string from "/public/static/userImg"

// desugars to
@module("/public/static/userImg.jpg") external userImg: unit = "default"

How will the errors look for users when they try to import an image as a URL? Are we leaving ourselves room to add this in the future?

The syntax literally desugars to @module externals, so the import doesn't do any specific logic (therefore you can use urls or whatever you please, as long as you use the es6 output), and your JS loader is responsible for showing the right error if a user tries to import invalid resources.
@IwanKaramazow sticked with the ES6 import conventions, so I am pretty sure we are future proof.

To the second point: one of the beautiful things for me, when I started out learning Reason, is that external just points to some external resource and the compiler figures out how to interop based on the context. In BuckleScript, annotations would make that an external to JS. In OCaml it could be to any other language.

The external keyword will still exist, and the import syntax is just "an alias" to the right external decorations (@module). All the beauty will still persist, and there is no change in the compiler preventing that.

@yawaramin if I'm reading this correct, you're proposing export {dirname: string => string, delimiter: string} from "path" to import values from JavaScript?

What if we come full circle and propose external {dirname: string => string, delimiter: string} from "path" 😂 or something like extimport 🤷♂
In all seriousness, however this pans out it will improve life for me (I do a lot of module externals in my current project) and encourage us to switch to ReScript syntax.
I do agree with the sentiment here that matching the ES6 style exactly, while convenient for aesthetic reasons, has a lot of potential downsides. Some pros and cons off the top of my head:

👎 High risk of confusion if it's explained as "write this like ES6 import syntax" when the semantics are very different
👎 Having an import keyword that exports what it creates while open doesn't is confusing
👍 Counter-point to the above: we already have include which does export what it adds
👍 The syntax overlap reduces the amount of things to learn for a new user (i.e. they already know it, now it just works differently)

Overall I think sort of export/external alternate keyword would help, but import isn't a terrible choice.

@yawaramin if I'm reading this correct, you're proposing export {dirname: string => string, delimiter: string} from "path" to import values from JavaScript?

What if we come full circle and propose external {dirname: string => string, delimiter: string} from "path" 😂 or something like extimport 🤷♂
In all seriousness, however this pans out it will improve life for me (I do a lot of module externals in my current project) and encourage us to switch to ReScript syntax.
I do agree with the sentiment here that matching the ES6 style exactly, while convenient for aesthetic reasons, has a lot of potential downsides. Some pros and cons off the top of my head:

👎 High risk of confusion if it's explained as "write this like ES6 import syntax" when the semantics are very different
👎 Having an import keyword that exports what it creates while open doesn't is confusing
👍 Counter-point to the above: we already have include which does export what it adds
👍 The syntax overlap reduces the amount of things to learn for a new user (i.e. they already know it, now it just works differently)

Overall I think sort of export/external alternate keyword would help, but import isn't a terrible choice.

@IwanKaramazow exactly, just swap import and replace with export.

@IwanKaramazow exactly, just swap import and replace with export.

@js import ... was a pretty nice suggestion in my opinion, although I'm unsure if @ryyppy meant it as a real suggestion 😄. Keeps the easy to remember syntax of import, and adds an extra tiny layer that clarifies what it actually is/does. I really like that personally.

@js import ... was a pretty nice suggestion in my opinion, although I'm unsure if @ryyppy meant it as a real suggestion 😄. Keeps the easy to remember syntax of import, and adds an extra tiny layer that clarifies what it actually is/does. I really like that personally.

@TheSpyder I know you were kidding, but I seriously thought about suggesting external {dirname: string => string, delimiter: string} from "path" :-) it has the advantage that it reuses an existing keyword.

@TheSpyder I know you were kidding, but I seriously thought about suggesting external {dirname: string => string, delimiter: string} from "path" :-) it has the advantage that it reuses an existing keyword.

@zth Yes, that was a real suggestion. The downside is that you now might occupy two lines:
@js
import {dirname: string => string} from "path"

The code looks nicer without the @js, but it might be clearer with? Maybe?

@zth Yes, that was a real suggestion. The downside is that you now might occupy two lines:
@js
import {dirname: string => string} from "path"

The code looks nicer without the @js, but it might be clearer with? Maybe?

I think it's clearer with, even if it occupies two lines. That'd give a gentle nudge to the user that it's indeed an import from js, and I think that would reduce the potential confusion.

I think it's clearer with, even if it occupies two lines. That'd give a gentle nudge to the user that it's indeed an import from js, and I think that would reduce the potential confusion.

@TheSpyder I know you were kidding, but I seriously thought about suggesting external {dirname: string => string, delimiter: string} from "path" :-) it has the advantage that it reuses an existing keyword.

I was only half kidding. It does neatly nod to what's really happening while still being almost entirely ES6 with one word swapped. But the moment we say "like ES6 import, but swap import to external" we start to run into the same documentation issues.

@zth Yes, that was a real suggestion. The downside is that you now might occupy two lines:
@js
import {dirname: string => string} from "path"

The code looks nicer without the @js, but it might be clearer with? Maybe?

Could you swap them?
import @js
{dirname: string => string} from "path"```

@TheSpyder I know you were kidding, but I seriously thought about suggesting external {dirname: string => string, delimiter: string} from "path" :-) it has the advantage that it reuses an existing keyword.

I was only half kidding. It does neatly nod to what's really happening while still being almost entirely ES6 with one word swapped. But the moment we say "like ES6 import, but swap import to external" we start to run into the same documentation issues.

@zth Yes, that was a real suggestion. The downside is that you now might occupy two lines:
@js
import {dirname: string => string} from "path"

The code looks nicer without the @js, but it might be clearer with? Maybe?

Could you swap them?
import @js
{dirname: string => string} from "path"```

this seems a bit aggressive by introducing import as a keyword and lots of new syntaxes. can we do it in a more incremental way, for example:
external "fs" {
  rmdirSync as rmdir: (string) => unit,
  rmdirSync as rmdirWith: (string, options) => string,
}

Note external is more meaningful than import, otherwise it's natural for other people to import things from rescript module.
You can always make things look better by adding new syntaxes, we must weight the pros and cons carefully

this seems a bit aggressive by introducing import as a keyword and lots of new syntaxes. can we do it in a more incremental way, for example:
external "fs" {
  rmdirSync as rmdir: (string) => unit,
  rmdirSync as rmdirWith: (string, options) => string,
}

Note external is more meaningful than import, otherwise it's natural for other people to import things from rescript module.
You can always make things look better by adding new syntaxes, we must weight the pros and cons carefully

I totally second @bobzhang 's idea here. Actually I was about to propose the same syntax with the external keyword 😄
To be honest I don't see any improvements using import instead of export as explained above 😕
On the other hand, I do like the new as syntax that makes bindings clearer and less fragile. Also, the new syntax should work for ambiant values.
To elaborate on @bobzhang 's example:
// Several bindings at once
external "fs" {
  rmdirSync as rmdir: (string) => unit,
  rmdirSync as rmdirWith: (string, options) => string,
}

// One binding at a time
external "fs" rmdirSync as rmdir: (string) => unit

external "fs" rmdirSync as rmdirWith: (string, options) => string

// Global binding
external setInterval: (unit => unit, float) => unit

external setInterval as whateverCrazyName: (unit => unit, float) => unit

// Classes
type date

@new
external Date as date: unit => date

// Forbidden keywords would reuse the \"..." syntax
@new
external \"type" as type_: string

Or something along those lines.
It would:

Makes bindings lighter and more robust (always felt a bit off to have = "importedValue" at the end of the external)
Easy to learn/remember as it partly relies on the import syntax
Easier to read
Works well for all bindings (while some might need some @attributes)
Nothing new to learn

I totally second @bobzhang 's idea here. Actually I was about to propose the same syntax with the external keyword 😄
To be honest I don't see any improvements using import instead of export as explained above 😕
On the other hand, I do like the new as syntax that makes bindings clearer and less fragile. Also, the new syntax should work for ambiant values.
To elaborate on @bobzhang 's example:
// Several bindings at once
external "fs" {
  rmdirSync as rmdir: (string) => unit,
  rmdirSync as rmdirWith: (string, options) => string,
}

// One binding at a time
external "fs" rmdirSync as rmdir: (string) => unit

external "fs" rmdirSync as rmdirWith: (string, options) => string

// Global binding
external setInterval: (unit => unit, float) => unit

external setInterval as whateverCrazyName: (unit => unit, float) => unit

// Classes
type date

@new
external Date as date: unit => date

// Forbidden keywords would reuse the \"..." syntax
@new
external \"type" as type_: string

Or something along those lines.
It would:

Makes bindings lighter and more robust (always felt a bit off to have = "importedValue" at the end of the external)
Easy to learn/remember as it partly relies on the import syntax
Easier to read
Works well for all bindings (while some might need some @attributes)
Nothing new to learn

oof, before we get this kind of syntax, I'd rather just have no changes. Less work on the syntax and a lot less to do educational / docs wise.
What does external "abc" even mean? that's complete off from a left to right reading perspective and looks like you are defining an external called abc.
At least keep the "from" keyword to make it somewhat understandable.
Messing around with two completely twisted kinds of "import syntaxes" when dealing with JS / ReScript codebases will just continue to be a huge pain.
Also, probably worth mentioning: import is already a reserved keyword today... you need to escape it, even if the keyword is not used.

oof, before we get this kind of syntax, I'd rather just have no changes. Less work on the syntax and a lot less to do educational / docs wise.
What does external "abc" even mean? that's complete off from a left to right reading perspective and looks like you are defining an external called abc.
At least keep the "from" keyword to make it somewhat understandable.
Messing around with two completely twisted kinds of "import syntaxes" when dealing with JS / ReScript codebases will just continue to be a huge pain.
Also, probably worth mentioning: import is already a reserved keyword today... you need to escape it, even if the keyword is not used.

before we get this kind of syntax, I'd rather just have no changes

That sounds like the most reasonable thing to do to be honest 😕
Introducing the new import syntax is just more confusing than anything, and doesn't solve any pain points.
From the look of it, there are 2 pain points:

The newcomers who have a hard time to understand the binding syntax (later on that one). But it doesn't seem that adding yet an other construct with import will make the complexity vanish, on the contrary it'll add complexity on top of complexity. Especially as it seems from a previous post that import would be used additionally to external. Again, not only is it a bit weird to use import to not import anything, but also it's not symetric with the way export currently works 😕 (the reason why export is sugar for @genType is beyond me, but that's another topic).
The people who have to write a lot of externals and would like a more lightweight/clearer syntax

Also, and while I understand ReScript is not the same as TS/Scala/C#/etc... it's always worth taking a look at how things are achieved in other languages. In TS the module binding system exists, and it's a .d.ts declaration file, Kotlin uses external, Scala.js uses something very close (with some annotations), so the concept is not that foreign, and shoudn't be a big hurdle for newcomers (and from my experience working with newcomers no one had a hard time with the external syntax, but rather the "proper" way to bind some kind of values, and to remember all the @ keywords, but that's an other issue, and import doesn't solve it either).
Taking the TS way, we could even consider using the resi files to bind js files when there is no equivalent res file, but that could be even more confusing. Adding yet an other extension like resd, using the same syntax as resi but binding external values is also an idea, and it would feel very familiar to TS developers.

before we get this kind of syntax, I'd rather just have no changes

That sounds like the most reasonable thing to do to be honest 😕
Introducing the new import syntax is just more confusing than anything, and doesn't solve any pain points.
From the look of it, there are 2 pain points:

The newcomers who have a hard time to understand the binding syntax (later on that one). But it doesn't seem that adding yet an other construct with import will make the complexity vanish, on the contrary it'll add complexity on top of complexity. Especially as it seems from a previous post that import would be used additionally to external. Again, not only is it a bit weird to use import to not import anything, but also it's not symetric with the way export currently works 😕 (the reason why export is sugar for @genType is beyond me, but that's another topic).
The people who have to write a lot of externals and would like a more lightweight/clearer syntax

Also, and while I understand ReScript is not the same as TS/Scala/C#/etc... it's always worth taking a look at how things are achieved in other languages. In TS the module binding system exists, and it's a .d.ts declaration file, Kotlin uses external, Scala.js uses something very close (with some annotations), so the concept is not that foreign, and shoudn't be a big hurdle for newcomers (and from my experience working with newcomers no one had a hard time with the external syntax, but rather the "proper" way to bind some kind of values, and to remember all the @ keywords, but that's an other issue, and import doesn't solve it either).
Taking the TS way, we could even consider using the resi files to bind js files when there is no equivalent res file, but that could be even more confusing. Adding yet an other extension like resd, using the same syntax as resi but binding external values is also an idea, and it would feel very familiar to TS developers.

Introducing the new import syntax is just more confusing than anything, and doesn't solve any pain points.

I strongly disagree with this. Writing bindings has historically been one of the most mentioned frictions when onboarding new users, mostly because current approach has nothing to do with JS way to import code, so one has to learn some random attributes like bs.new or whatever. In that sense, I very much appreciate this proposal, and I believe it is valuable because it brings bindings syntax closer to what JS users are used to already.
I also agree that (ab)using import for this case is confusing, but I also think (ab)using external to then reinvent totally different semantics (that have nothing to do with OCaml external) is equally confusing.
What if there was a totally different word used for this? e.g. use:
use { delimiter: string } from "path"
use school: string from "school"
use * as leftPad: (string, int) => string from "leftPad"

That way there is no room from confusion, but users still can leverage syntactic knowledge about how values are imported in JS thanks to the proposal.

Introducing the new import syntax is just more confusing than anything, and doesn't solve any pain points.

I strongly disagree with this. Writing bindings has historically been one of the most mentioned frictions when onboarding new users, mostly because current approach has nothing to do with JS way to import code, so one has to learn some random attributes like bs.new or whatever. In that sense, I very much appreciate this proposal, and I believe it is valuable because it brings bindings syntax closer to what JS users are used to already.
I also agree that (ab)using import for this case is confusing, but I also think (ab)using external to then reinvent totally different semantics (that have nothing to do with OCaml external) is equally confusing.
What if there was a totally different word used for this? e.g. use:
use { delimiter: string } from "path"
use school: string from "school"
use * as leftPad: (string, int) => string from "leftPad"

That way there is no room from confusion, but users still can leverage syntactic knowledge about how values are imported in JS thanks to the proposal.

I strongly disagree with this. Writing bindings has historically been one of the most mentioned frictions when onboarding new users, mostly because current approach has nothing to do with JS way to import code, so one has to learn some random attributes like bs.new or whatever. In that sense, I very much appreciate this proposal, and I believe it is valuable because it brings bindings syntax closer to what JS users are used to already.

I'd like to second this almost in its entirety.  This is a good thing to talk about.  I want to thank the original poster and those they consulted for their efforts tacking "the bindings problem". I would also like to observe that in the future there are fewer sunk costs and less ego involved with feedback on a proposal versus an implementation. Perhaps I missed the original proposal? Perhaps even a simple established RFP procedure would alleviate this in the future?
When I hit my personal wall with bindings, it was not the syntax that confused me (other than = "someString" being a small speed bump).  It was typing, and understanding what Rescript/Reason wanted me to do.  The problem was literally what to type as the type, particularly for objects, polymorphism, when this abstract type thing was necessary, etc.
It seems to me like a new syntax does nothing to fix that actual pain, yet incurs all the typical costs of a more complicated (larger) language syntax (with the added pain of having two language keywords to express the same concept). In addition, it incurs the overhead of asking new reason users to unlearn a concept from javascript. For example, as a new user to reason, one of the very first things that confused me was "how do I reference something in this other file".  Should I have been presented with an import syntax, you bet your butt I would have tried to use it, because that's what I knew to use for javascript.  And while we could easily throw a yellow box up on a docs page explaining this difference at the top, I would gently suggest adding new syntax that immediately wants for a warning that it does not do what you think it does, is not ideal.
In sum, I would question the underlying assumption that syntax is the problem (but am open to being shown otherwise). That being the case, I think the problems with any new keyword might outweigh the benefits, and would prefer it not be added until we can establish that people are really being tripped up on the syntax of externals versus the deeper issues around type modeling a dynamic language with ml.
FWIW, I found Typescript declaration files extremely esoteric when I learned Typescript (and still think so in some respects, lol).  But it just a non-issue since coverage is good with with definitely typed. Are there any immediate problems with going that route instead: having a centralized, easy to search, easy to contribute repository of bindings to which we can refer new community members to both for examples of bindings (or simply pre-written ones)? Not every solution to every problem is an engineering one, here documentation, advocacy, or a product like a definitely typed for rescript might help address the same issue as this PR

I strongly disagree with this. Writing bindings has historically been one of the most mentioned frictions when onboarding new users, mostly because current approach has nothing to do with JS way to import code, so one has to learn some random attributes like bs.new or whatever. In that sense, I very much appreciate this proposal, and I believe it is valuable because it brings bindings syntax closer to what JS users are used to already.

I'd like to second this almost in its entirety.  This is a good thing to talk about.  I want to thank the original poster and those they consulted for their efforts tacking "the bindings problem". I would also like to observe that in the future there are fewer sunk costs and less ego involved with feedback on a proposal versus an implementation. Perhaps I missed the original proposal? Perhaps even a simple established RFP procedure would alleviate this in the future?
When I hit my personal wall with bindings, it was not the syntax that confused me (other than = "someString" being a small speed bump).  It was typing, and understanding what Rescript/Reason wanted me to do.  The problem was literally what to type as the type, particularly for objects, polymorphism, when this abstract type thing was necessary, etc.
It seems to me like a new syntax does nothing to fix that actual pain, yet incurs all the typical costs of a more complicated (larger) language syntax (with the added pain of having two language keywords to express the same concept). In addition, it incurs the overhead of asking new reason users to unlearn a concept from javascript. For example, as a new user to reason, one of the very first things that confused me was "how do I reference something in this other file".  Should I have been presented with an import syntax, you bet your butt I would have tried to use it, because that's what I knew to use for javascript.  And while we could easily throw a yellow box up on a docs page explaining this difference at the top, I would gently suggest adding new syntax that immediately wants for a warning that it does not do what you think it does, is not ideal.
In sum, I would question the underlying assumption that syntax is the problem (but am open to being shown otherwise). That being the case, I think the problems with any new keyword might outweigh the benefits, and would prefer it not be added until we can establish that people are really being tripped up on the syntax of externals versus the deeper issues around type modeling a dynamic language with ml.
FWIW, I found Typescript declaration files extremely esoteric when I learned Typescript (and still think so in some respects, lol).  But it just a non-issue since coverage is good with with definitely typed. Are there any immediate problems with going that route instead: having a centralized, easy to search, easy to contribute repository of bindings to which we can refer new community members to both for examples of bindings (or simply pre-written ones)? Not every solution to every problem is an engineering one, here documentation, advocacy, or a product like a definitely typed for rescript might help address the same issue as this PR

As a ReasonML/ReScript beginner, what I felt while writing some bindings, syntaxes/keywords weren't really obstacles, but It made it easy to infer that the different behavior.
The reason why binding became difficult for me was to write bindings for the point-free style abstraction, and for this, I had to abandon the zero-cost binding many times.
In fact, these courses have helped me a lot in learning the reason-ish way. So I think it's a much more helpful approach that to provide a binding template like flow-typed does or a converter like ReasonablyTyped in case users are sometimes confused about how to achieve binding properly.

As a ReasonML/ReScript beginner, what I felt while writing some bindings, syntaxes/keywords weren't really obstacles, but It made it easy to infer that the different behavior.
The reason why binding became difficult for me was to write bindings for the point-free style abstraction, and for this, I had to abandon the zero-cost binding many times.
In fact, these courses have helped me a lot in learning the reason-ish way. So I think it's a much more helpful approach that to provide a binding template like flow-typed does or a converter like ReasonablyTyped in case users are sometimes confused about how to achieve binding properly.

If I understand correctly the problems the people pointed out with the proposed syntax are:

different semantics than JS (it imports and exports at the same time by default)
Polluting keyword space

as previously mentioned the import here closely follows the semantics of include. Therefore I think we can have a self explanatory import-like mechanism (hopefully not too difficult to parse) with:
include { delimiter: string } from “path”

If I understand correctly the problems the people pointed out with the proposed syntax are:

different semantics than JS (it imports and exports at the same time by default)
Polluting keyword space

as previously mentioned the import here closely follows the semantics of include. Therefore I think we can have a self explanatory import-like mechanism (hopefully not too difficult to parse) with:
include { delimiter: string } from “path”

@jchavarri

Introducing the new import syntax is just more confusing than anything, and doesn't solve any pain points.

I strongly disagree with this.

I may have poorly explained my point of view here (especially because as it appears in your comment, we agree on mostly everything 😄 ).
I do think an update of the syntax is desired, and could solve some of the issues listed here, here, and there. But import sounds really confusing as it basically doesn't import anything, that's it. Words have meaning, and using import just for the sake of familiarity is probably not a great choice, but again, that's just my point of view after trying to understand the binding system myself, and working regularly with new comers to the language.

so one has to learn some random attributes like bs.new or whatever

Agree, that's, to me, the main pain point when learning the external (with the expected type), but import doesn't solve it. It only drops the @module annotation, that's it (and that's probably the less confusing part of the external system 😄). It seems external and the other @something will still be around for a while according to @ryyppy here (last paragraph).
But again, and even though I totally agree a small syntax update would be very welcome (less annotations, less confusion regarding the  = "???" syntax, etc...), let's keep in mind the syntax is clearly not the biggest obstacle in the learning curve of externals.

Slightly unrelated, and while @ryyppy and other team members are currently doing a great job with the documentation, one of the biggest issue when binding a value used to be the lack of clear documentation, with case by case examples (there was no official and curated cheatsheet for annotations for a looooong time for instance).

@jchavarri

Introducing the new import syntax is just more confusing than anything, and doesn't solve any pain points.

I strongly disagree with this.

I may have poorly explained my point of view here (especially because as it appears in your comment, we agree on mostly everything 😄 ).
I do think an update of the syntax is desired, and could solve some of the issues listed here, here, and there. But import sounds really confusing as it basically doesn't import anything, that's it. Words have meaning, and using import just for the sake of familiarity is probably not a great choice, but again, that's just my point of view after trying to understand the binding system myself, and working regularly with new comers to the language.

so one has to learn some random attributes like bs.new or whatever

Agree, that's, to me, the main pain point when learning the external (with the expected type), but import doesn't solve it. It only drops the @module annotation, that's it (and that's probably the less confusing part of the external system 😄). It seems external and the other @something will still be around for a while according to @ryyppy here (last paragraph).
But again, and even though I totally agree a small syntax update would be very welcome (less annotations, less confusion regarding the  = "???" syntax, etc...), let's keep in mind the syntax is clearly not the biggest obstacle in the learning curve of externals.

Slightly unrelated, and while @ryyppy and other team members are currently doing a great job with the documentation, one of the biggest issue when binding a value used to be the lack of clear documentation, with case by case examples (there was no official and curated cheatsheet for annotations for a looooong time for instance).

Introducing the new import syntax is just more confusing than anything, and doesn't solve any pain points.

I strongly disagree with this. Writing bindings has historically been one of the most mentioned frictions when onboarding new users, mostly because current approach has nothing to do with JS way to import code, so one has to learn some random attributes like bs.new or whatever. In that sense, I very much appreciate this proposal, and I believe it is valuable because it brings bindings syntax closer to what JS users are used to already.
I also agree that (ab)using import for this case is confusing, but I also think (ab)using external to then reinvent totally different semantics (that have nothing to do with OCaml external) is equally confusing.
What if there was a totally different word used for this? e.g. use:
use { delimiter: string } from "path"
use school: string from "school"
use * as leftPad: (string, int) => string from "leftPad"

That way there is no room from confusion, but users still can leverage syntactic knowledge about how values are imported in JS thanks to the proposal.

I strongly agree with this. But please don't make use a keyword, because in our codebase we have a pattern with a module and a use function as a React hook (for instance let dimensions = WindowDimensions.use().

Introducing the new import syntax is just more confusing than anything, and doesn't solve any pain points.

I strongly disagree with this. Writing bindings has historically been one of the most mentioned frictions when onboarding new users, mostly because current approach has nothing to do with JS way to import code, so one has to learn some random attributes like bs.new or whatever. In that sense, I very much appreciate this proposal, and I believe it is valuable because it brings bindings syntax closer to what JS users are used to already.
I also agree that (ab)using import for this case is confusing, but I also think (ab)using external to then reinvent totally different semantics (that have nothing to do with OCaml external) is equally confusing.
What if there was a totally different word used for this? e.g. use:
use { delimiter: string } from "path"
use school: string from "school"
use * as leftPad: (string, int) => string from "leftPad"

That way there is no room from confusion, but users still can leverage syntactic knowledge about how values are imported in JS thanks to the proposal.

I strongly agree with this. But please don't make use a keyword, because in our codebase we have a pattern with a module and a use function as a React hook (for instance let dimensions = WindowDimensions.use().

If I understand correctly the problems the people pointed out with the proposed syntax are:

different semantics than JS (it imports and exports at the same time by default)
Polluting keyword space

as previously mentioned the import here closely follows the semantics of include. Therefore I think we can have a self explanatory import-like mechanism (hopefully not too difficult to parse) with:
include { delimiter: string } from “path”

Love this! 👆 We don't lose a keyword (or use a confusing one like import) and it is pretty self explanatory (the other include also exposes the contents outside the module.

If I understand correctly the problems the people pointed out with the proposed syntax are:

different semantics than JS (it imports and exports at the same time by default)
Polluting keyword space

as previously mentioned the import here closely follows the semantics of include. Therefore I think we can have a self explanatory import-like mechanism (hopefully not too difficult to parse) with:
include { delimiter: string } from “path”

Love this! 👆 We don't lose a keyword (or use a confusing one like import) and it is pretty self explanatory (the other include also exposes the contents outside the module.

Great to see all the discussion that's developed over the past days. Most capture what I've been mulling over away from this thread quite well. I think I'm left with two main thoughts.
First, moving away from import to something else solves most of my worries in that regards, since you don't bring the baggage that people associate with that keyword from JavaScript and break that behaviour, but make it clear that you're introducing something new.
Since we're constantly talking about making 'bindings' is there a reason we haven't considered the bind keyword yet? i.e bind { delimiter: type } from "path"? The advantage is that if you type in rescript bind you'll probably already get existing documentation and articles for bindings? The only downside I can come up with is that it's an existing JavaScript function name.
Secondly, so far I feel like we're introducing a syntax that only covers parts of the issues. This has been mentioned before. I share the feeling that the syntax actually only improves the easiest parts of the syntax. Removing the annotations that I struggled with the least when I was a newcomer to Reason. Some of the more difficult parts are left intact.
The worry here is that the documentation moves to the new syntax and leaves users stranded if that syntax isn't adequate forcing them to use the external syntax, which is then less likely to be documented well. The most notable example is probably "import values from JavaScript modules with @as and polyvariants". That actually taught me some things I haven't been able to figure out before.
(I have to note that before writing this I did a cursory search of the ReScript docs and am now able to find examples of most of the decorators that I wasn't able to find in previous searches. I'll see if I can contribute by linking the list in the cheatsheet to the documentation for each decorator.)

Great to see all the discussion that's developed over the past days. Most capture what I've been mulling over away from this thread quite well. I think I'm left with two main thoughts.
First, moving away from import to something else solves most of my worries in that regards, since you don't bring the baggage that people associate with that keyword from JavaScript and break that behaviour, but make it clear that you're introducing something new.
Since we're constantly talking about making 'bindings' is there a reason we haven't considered the bind keyword yet? i.e bind { delimiter: type } from "path"? The advantage is that if you type in rescript bind you'll probably already get existing documentation and articles for bindings? The only downside I can come up with is that it's an existing JavaScript function name.
Secondly, so far I feel like we're introducing a syntax that only covers parts of the issues. This has been mentioned before. I share the feeling that the syntax actually only improves the easiest parts of the syntax. Removing the annotations that I struggled with the least when I was a newcomer to Reason. Some of the more difficult parts are left intact.
The worry here is that the documentation moves to the new syntax and leaves users stranded if that syntax isn't adequate forcing them to use the external syntax, which is then less likely to be documented well. The most notable example is probably "import values from JavaScript modules with @as and polyvariants". That actually taught me some things I haven't been able to figure out before.
(I have to note that before writing this I did a cursory search of the ReScript docs and am now able to find examples of most of the decorators that I wasn't able to find in previous searches. I'll see if I can contribute by linking the list in the cheatsheet to the documentation for each decorator.)

The worry here is that the documentation moves to the new syntax and leaves users stranded if that syntax isn't adequate forcing them to use the external syntax, which is then less likely to be documented well.

That's why I suggest incremental improvement for most common use cases

The worry here is that the documentation moves to the new syntax and leaves users stranded if that syntax isn't adequate forcing them to use the external syntax, which is then less likely to be documented well.

That's why I suggest incremental improvement for most common use cases

@bobzhang @IwanKaramazow @ryyppy Maybe this have been discussed somewhere, but how does the proposal in this PR fit with the other (and I believe more ambitious) proposal of having a JavaScript-like DSL for FFI that was discussed in https://github.com/rescript-lang/rescript-compiler/issues/3618?
That proposal (imo) was really compelling from a teaching / onboarding newcomers perspective, as it removes the need to learn a list of new custom attributes and leverages the knowledge of JS syntax new users will most probably have already.
If it is still planned, an "external syntax roadmap" would be valuable in order for everyone to visualize and understand the path to progressively move towards the DSL for FFI end goal. Also, if that DSL for FFI would eventually happen, then I'd tend to agree with the comments above that adopting this proposal would have to be better justified, to not pile on additional syntax changes, which I believe the community is still recovering from.

@bobzhang @IwanKaramazow @ryyppy Maybe this have been discussed somewhere, but how does the proposal in this PR fit with the other (and I believe more ambitious) proposal of having a JavaScript-like DSL for FFI that was discussed in https://github.com/rescript-lang/rescript-compiler/issues/3618?
That proposal (imo) was really compelling from a teaching / onboarding newcomers perspective, as it removes the need to learn a list of new custom attributes and leverages the knowledge of JS syntax new users will most probably have already.
If it is still planned, an "external syntax roadmap" would be valuable in order for everyone to visualize and understand the path to progressively move towards the DSL for FFI end goal. Also, if that DSL for FFI would eventually happen, then I'd tend to agree with the comments above that adopting this proposal would have to be better justified, to not pile on additional syntax changes, which I believe the community is still recovering from.

FWIW going back over this I really like @bobzhang 's incremental proposal here: https://github.com/rescript-lang/syntax/pull/217#issuecomment-754326330
It will keep any current docs and blogs about externals relevant to the problem, remove the ugliest parts of the current syntax, and given time we might just find there is no real need for a new keyword.

FWIW going back over this I really like @bobzhang 's incremental proposal here: https://github.com/rescript-lang/syntax/pull/217#issuecomment-754326330
It will keep any current docs and blogs about externals relevant to the problem, remove the ugliest parts of the current syntax, and given time we might just find there is no real need for a new keyword.

If you wanted to do the incremental approach in #217 - what if we tried to match the typescript semantics?
declare module "fs" {
  export let rmdirSync: (string) => unit;
}

For exporting with a different type signature and name - I'm not 100% sure what we do, but this is valid TS -
declare module "fs" {
    let rmdirSync: (string) => unit;
    export {rmdirSync as rmdirWith};
}

I don't fully know how that would work to do what we want to do though

If you wanted to do the incremental approach in #217 - what if we tried to match the typescript semantics?
declare module "fs" {
  export let rmdirSync: (string) => unit;
}

For exporting with a different type signature and name - I'm not 100% sure what we do, but this is valid TS -
declare module "fs" {
    let rmdirSync: (string) => unit;
    export {rmdirSync as rmdirWith};
}

I don't fully know how that would work to do what we want to do though

for the reference, we had similar discussions before: https://github.com/rescript-lang/rescript-compiler/issues/2067#issuecomment-346546605


Add support for about:blank

Currently it says Error: EXTENSION can't be enabled on this page., but technically extensions can ask for about:blank I think

about:blank is not possible: https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/executeScript#matchaboutblank

The code cannot be inserted in top-level about: frames.

I think there's no "about blank" permission, so webext-permission-toggle cannot request it. matchAboutBlank is exclusive to frames of pages you have access to.


Change text on main page to be about campaigns

The text on the main page should reflect that people are carpooling to help campaigns. Maybe "Find carpools heading to campaign offices".

Existing text is mostly a placeholder. I'd like to see a bit more text designed to draw people in and use the site.

Totally understood. If we want to show the site to campaign managers, though, it might make more sense to them if it had something to do with elections.

fixed up a bit (would still be nice to get a copywriter eventually, but i think it's good for MVP)


Check if no project name is present.

Running "lambo" with no arguments (project name) wreaks all sorts of havoc.
I ran "lambo" like I would "valet" or "laravel" to see the list of commands and a description and nuked the project that was my current working directory.
Ideally we would set this up using something like: mnapoli/silly, but I figured this would be an "MVP" version of the feature.
Just throwing this out there, if it's worth it I would be happy to give "mnapoli/silly" a shot to provide a more elegant interface.

Oh geez.
Thanks Caleb. Sorry it nuked all the things.
I'm interested in Silly... for now I want to keep it bash, just so we don't run into too many crazy PHP version constraints/etc. But maybe we will be better off that way..

Thanks for pulling it in.
Agreed, I like the simplicity of the bash file. We'll keep an eye on it.


i can't find out why i am getting this error

[script:PoliceEMSActi] SCRIPT ERROR: @PoliceEMSActivity/server.lua:181: bad argument #1 to 'pairs' (table expected, got nil)

Ensure your role list in your config is setup correctly.


Resource processor - Re-instate az login and az acr login commands prior to porter explain command to fix microsoft/AzureTRE#3950

Resolves #3950
What is being addressed
Re-instate az login and az acr login commands prior to porter explain command to fix microsoft/AzureTRE#3950

/test-extended

/test-extended bdd9b5e

Hi @tim-allen-ck I've had a look at the test failures and I don't think its related to my change, but let me know if you think otherwise.

Hi @tim-allen-ck I've had a look at the test failures and I don't think its related to my change, but let me know if you think otherwise and I'll take another look.

Yeah nothing to do with your code changes, looks like an environment issue, I'm looking into it.

/test

/test 488b238

/test bdd9b5e

@jonnyry can you update the commit with the latest main branch?

@tim-allen-ck updated to latest

/test d518d52


Need Open ID connect in Grocery Sync Android for release verification

Here is the repo: https://github.com/couchbaselabs/GrocerySync-Android/tree/feature/openid
Current status:

Both AuthCode and Implicit flow with Google Sign-in were implemented.
The AuthCode flow is current blocked by #1315 to start the second replication (push) and the application screen.


603 update sbt

Closes #603

Summary:
Fix an execution bug for running examples with sbt 1.8.0 or higher
I think this change in Fork behavior is the reason for this issue.
https://github.com/sbt/sbt/commit/ca45370ea18463c27135293f35856ea6f070c0d0
So I am filtering out line.separator Java option as a solution

Would be neat to get https://github.com/ScalaConsultants/mesmer/pull/612 merged first, then we could use the updated CI to validate this PR.

@hwgonz I merged https://github.com/ScalaConsultants/mesmer/pull/612 that would test this PR automatically. Could you resolve the conflicts? Is there a chance that with the current project structure, the fix will not be required (that's my long shot ;) )?


router: implement a proper shutdown mechanism

The "running" flag is now accessed as an atomic (so with sequential ordering per the Go memory model). Added a shutdown entry point which cannot race with initialization.
Fixes #4116

This change is

I agree. I don't much see a real use case for sharing the management of a router between multiple threads but it is theoretically possible. Multiple threads could also fight over interfaces during initialization, which is also unlikely to produce sensible results. Note that after a call to Shutdown, the router is committed to terminating, so there's not much incentive in using Shutdown() as a way to allow reconfigurations. As things stand at the moment, the shutdown mechanism only exists so unit tests can terminate the router. I almost did what you described (i.e. more than two states) and then stopped myself...YAGNI.
But if that loose end bothers you, you are mot welcome to file a new issue (or re-open yours) and propose such an improvement. It shouldn't add much complexity, so I won't object on those grounds.


The Automate datastore is missing ec2 methods

The latest versions is missing the Methods from Integration\Amazon\EC2 and Integration\Amazon\RDS
Which causes this error on setting up an EC2 instance
[----] I, [2016-10-28T10:27:32.060148 #3264:699998]  INFO -- : Q-task_id([miq_provision_1000000000105]) Processing State=[PostProvision2]
[----] I, [2016-10-28T10:27:32.060457 #3264:699998]  INFO -- : Q-task_id([miq_provision_1000000000105]) Following Relationship [miqaedb:/Integration/Amazon/EC2/Methods/EC2_Synchronize_Tags#create]
[----] E, [2016-10-28T10:27:32.185635 #3264:699998] ERROR -- : Q-task_id([miq_provision_1000000000105]) Class [Integration/Amazon/EC2/Methods] not found in MiqAeDatastore
[----] I, [2016-10-28T10:27:32.185787 #3264:699998]  INFO -- : Q-task_id([miq_provision_1000000000105]) Followed  Relationship [miqaedb:/Integration/Amazon/EC2/Methods/EC2_Synchronize_Tags#create]
[----] E, [2016-10-28T10:27:32.185949 #3264:699998] ERROR -- : Q-task_id([miq_provision_1000000000105]) State= running  raised exception:
[----] W, [2016-10-28T10:27:32.186156 #3264:699998]  WARN -- : Q-task_id([miq_provision_1000000000105]) Error in State=[PostProvision2]
[----] I, [2016-10-28T10:27:32.186346 #3264:699998]  INFO -- : Q-task_id([miq_provision_1000000000105]) In State=[PostProvision2], invoking [on_error] method=[update_provision_status(status => 'Error Applying PostProvision1 Customizations')]
I copied the Methods from a previous version and all worked ok.

You should not have to copy the methods back in. I moved them to the statemachines class. I have just corrected to repo so that they are pointed to the correct class.
Thanks for pointing this one out.


Godot crashes when deleting a child UI element in a callback

Godot version: 3.1 beta 5
OS/device including version: Win 10
Issue description:
I created a very simple tooltip UI element with simple logic. If the user's mouse enters the parent element, it creates a tooltip next to the element. If the mouse exits the parent, the tooltip is deleted.
If the user moves their mouse on and off the parent element without mousing over the tooltip, it is fine. If the user moves their mouse from the parent element to the tooltip, Godot crashes.
I worked around this crash by not deleting the tooltip in the mouse_exited callback for the parent element and instead deleting it on the next _Process call.
Steps to reproduce:
I attached a project with a test scene (Scenes/test.tscn), open that and hover your mouse over the UI element then move it to the right to cause a crash.
Relevant code that causes the crash is in Src/Godot/UI/AttributeItem.cs
Minimal reproduction project:
Game.zip

So here is the problematic code:
AttributeItem.cs
    private void MouseExit() // this is called by mouse_exited signal
    {
        if (m_tooltip != null)
        {
            m_del = true;

            // this code results in the crash
            RemoveChild(m_tooltip);
            m_tooltip.Free();
            m_tooltip = null;
        }
    }

You are using Free, which immediately destroys the node. In some cases that means dangling pointers may cause a crash like here. You can try using queue_free() instead of remove and free.
Maybe you can also try CallDeferred("free").

I tried QueueFree and CallDeferred("free") instead, and while it does not crash, it still causes errors:
E 0:00:08:0622   Condition ' !is_inside_tree() ' is true. returned: get_transform()   <C Source>     scene/2d/canvas_item.cpp:478 @ get_global_transform()
For now i'm happy with my workaround where i just delete the element the next time _Process is called.

@nuke-makes-games one of my two workarounds (queue free) still expects the node to be in the tree, are they both causing errors?

Both gave the same result, though I was calling RemoveChild in both tests so maybe that tainted the results.

Assigned @reduz, maybe he knows how to properly fix it and safely apply to 3.1

It would be good to have a GDScript-based MRP, to rule out a potential issue with the Mono module.

an anyone still reproduce this bug in Godot 3.2.2 or any later release?
If yes, please ensure that an up-to-date Minimal Reproduction Project (MRP) is included in this report (a MRP is a zipped Godot project with the minimal elements necessary to reliably trigger the bug). You can upload ZIP files in an issue comment with a drag and drop.
(the attached project doesn't run in 3.2.2 due to errors; also a GDScript project would be useful, as noted comment above)

Closing due to lack of update. Please comment if you can still reproduce this issue in the latest stable version of Godot.


Week 3 Scrum Report

David Mwita

What did you work on this past iteration (2 weeks)?

Project Requirements document and UI sketches.

What were any major issues/challenges you ran into?

No challenges encountered so far

What do you plan to work on for this coming iteration (2 weeks)?

Launching a frontend via Vite, begin working on the Home page and the Recipe page


Autofunction: Let class docstring override @property functions

📚 Context
When the docstring parser creates the dictionary for a class in streamlit.json, @property-decorated functions get saved under the "property" key. Any "Attributes" in the docstring get saved under the "args" key. When Autofunction renders a class, the "properties" and "args" are combined under the "Attribute" header. Up until now, a class attribute was not recorded in "Attributes" if it existed as an @property-decorated method, to avoid duplicates.
This PR is needed to better support the StreamlitPage class for 1.36.0.
🧠 Description of Changes
This PR includes a check for duplicate attributes for classes. If an attribute exists in both the docstring "Attributes" list and as a @property-decorated function, Autofunction will only render the attribute from the docstring.
When an @property attribute is rendered, it includes an anchor link, expecting another Autofunction below to render the method. Not all attributes exists as @property-decorated functions that can be picked up automatically, and not all @property-decorated functions need to be fully rendered with their own Autofunction. Therefore, this PR gives the ability to override the automatic detection of @property-decorated methods.
This doesn't impact the current instances where "Attributes" in the docstring supplement the @property-decorated methods. (e.g. AppTest)
Contribution License Agreement
By submitting this pull request you agree that all contributions to this project are made under the Apache 2.0 license.

I will merge this singe-commit PR without squashing to simplify things. (I merged this commit into release instead of cherry-pick, so if it gets merged without squashing I won't have to revert it on release branch or deal with the conflict.)

LGTM and is a good addition!


Name and Year Lookups Not Functioning

Acknowledgement / Overview
I realize that moviescore has not had a commit since 2017 and that it's likely not being actively maintained.  I wanted to point out that it looks like some of the functions are no longer working properly.
I have used the examples from the README to illustrate.
Environment
# go version
go version go1.12.9 linux/amd64
# moviescore --version
moviescore version 0.1
#

Moviescore Failures
Name Fails
# moviescore "The Dark Knight"

------------------------------------------------------
  __  __            _         _____
 |  \/  |          (_)       / ____|
 | \  / | _____   ___  ___  | (___   ___ ___  _ __ ___
 | |\/| |/ _ \ \ / / |/ _ \  \___ \ / __/ _ \| '__/ _ \
 | |  | | (_) \ V /| |  __/  ____) | (_| (_) | | |  __/
 |_|  |_|\___/ \_/ |_|\___| |_____/ \___\___/|_|  \___|
------------------------------------------------------

The Movie Does not seem to exist!
Tip: If you are using spaces in your film name, enclose the movie name in double quotes!
#

Year Value Fails
# moviescore -y 2016 "arrival"

------------------------------------------------------
  __  __            _         _____
 |  \/  |          (_)       / ____|
 | \  / | _____   ___  ___  | (___   ___ ___  _ __ ___
 | |\/| |/ _ \ \ / / |/ _ \  \___ \ / __/ _ \| '__/ _ \
 | |  | | (_) \ V /| |  __/  ____) | (_| (_) | | |  __/
 |_|  |_|\___/ \_/ |_|\___| |_____/ \___\___/|_|  \___|
------------------------------------------------------

The Movie Does not seem to exist!
Tip: If you are using spaces in your film name, enclose the movie name in double quotes!

You will feel utterly numb after the screening of The Dark Knight. The film is bleak and brilliant.
 -------------------
To talk of Heath Ledger's performance is difficult, merely because, as gigantic as it is, it is only one important feature of an intricately wrought canvas.
 -------------------
The Dark Knight is probably the smartest and most stylish action movie since the "The Matrix." It thinks and philosophizes. The subject it thinks and philosophizes about, perhaps not surprisingly, considering the times, is the Iraq war.
 -------------------
An exceptionally smart, brooding picture with some terrific performances.
 -------------------
The Dark Knight is a film that's fantastic on the action front, seeds its acrobatics in its own reality, and always feels relevant even when its ideas are drowned out by clatter.
 -------------------
Christopher Nolan is much, much smarter than your average filmmaker.
 -------------------
The definitive movie of its genre and the best Batman film to date
 -------------------
Heath Ledger is great.
 -------------------
Not just a perfect comic book movie, not just a perfect Batman movie, but darn-near a perfect movie, full stop.
 -------------------
The movie's a real neo-noir all right, wallowing in darkness, thrilled with how bad we are, and getting such a kick out of our impending doom it cheers you right up.
 -------------------
A film is only as good as its villain. By that standard, The Dark Knight achieves true greatness.
 -------------------
The Dark Knight always ought to be played on the biggest screen possible, and played loud, like a Led Zepplin song. Director Christopher Nolans' skyscapes, the helicopter shots and views from the 200th floor, are IMAX at its best.
 -------------------
#

Parental Guide Succeeds
moviescore -pg inception

------------------------------------------------------
  __  __            _         _____
 |  \/  |          (_)       / ____|
 | \  / | _____   ___  ___  | (___   ___ ___  _ __ ___
 | |\/| |/ _ \ \ / / |/ _ \  \___ \ / __/ _ \| '__/ _ \
 | |  | | (_) \ V /| |  __/  ____) | (_| (_) | | |  __/
 |_|  |_|\___/ \_/ |_|\___| |_____/ \___\___/|_|  \___|
------------------------------------------------------

 Parental Guide:
Reference Url:  http://www.imdb.com/title//parentalguide
 Sex and Nudity

 Violence And Gore

 Profanity

 Alcohol/Drugs/Smoking

 Frightening/Intense Scenes
#

Hi @pierow2k  ,
Thanks for the report! There were some changes in the API which the app was depending upon. Made those changes, now it should start working again!
Cheers!

Thanks @BharatKalluri !


ARROW-21 Test PyMongoArrow documentation build in CI

Also addresses ARROW-41

Moving back to draft so I can create the appropriate RTD config file.

There are surprisingly a lot of changes to setup.py here. Can you explain?

I was refactoring to support installing from the libbson conda package without requiring an environment variable (since we can't set it on RTD).  I also wanted to preserve the ability to use the system libbson (I have the homebrew version installed locally).  I noticed that the IS_WIN vs Posix handling branch were getting muddled, so I separated it out into different functions, which allowed me to clean it up a lot.

Interesting. Is supporting libbson conda needed? It seems like we could just run ./build-libbson.sh like usual before building the docs.

It seems like we could just run ./build-libbson.sh like usual before building the docs.

ReadTheDocs does not yet support running scripts prior to pip install ..  However, I found the solution: if you install pkg-config in the conda environment, then that version of pkg-config looks in the conda environment for its libraries, and it works with no changes to setup.py!


Adding parallel-from-list example

cc @reviewbybees

This pull request originates from a CloudBees employee. At CloudBees, we require that all pull requests be reviewed by other CloudBees employees before we seek to have the change accepted. If you want to learn more about our process please see this explanation.

:bee:

:bee:


HttpStore refactor

Coverage remained the same at 100.0% when pulling 69e93167340d5f5953f0af017d1dad14dc12547e on http-refactor into be095a41401ab92dbf450d34f4fe0b4bab47f3d0 on master.


Use go-digest package

Switch from github.com/docker/distribution/digest to github.com/opencontainers/go-digest.
Vendor a new version of github.com/docker/distribution that uses go-digest.
ping @stevvooe

LGTM

LGTM


Use rust-bindgen to generate cubeb-core/src/ffi.rs

cubeb-core/src/ffi.rs is generated by hand.  Switch to using bindgen.
From @kinetiknz PR/7

This looks like a combination of a bindgen generated file and hand editing. I'm concerned that this will be difficult to maintain in the future, so I'd rather we simply use bindgen directly for all FFI level bindings (and let them deal with the bugs), then write cleaner Rust-y APIs on top of whatever bindgen spits out.

FFI has been completely replaced in v0.4


Is there a more detailed benchmark report?

what is wrk options ? (like connections and thread)
thanks

Sorry for the late reply. In fact, we use wrk 4.1.0 and the simple options look like wrk -t64 -c200 -d10m --script=$scriptFile --latency http://host:port


No verification mail is send

On localhost it works perfectly, but online tests always result with:

The user gets created in the database, but no mail is send. Email settings are the same as when I tried on localhost.
Any ideas? Thanks!

Hi @mgk89, without more details, my guess would be an issue with your mail server credentials or perhaps some sort of firewall setting, but I can't be sure without additional information. Since circumstances vary so much from project to project and our mailer utilizes an external library, I would recommend opening an issue with your configuration details on the PHPMailer author's repository and see if they have any suggestions. Here's their repo: https://github.com/PHPMailer/PHPMailer
Sorry it's not working for you, please let us know if you find an issue in our code that is causing this problem!

Hi, thanks for your answer!
I figured it out, it was due to restrictions from my provider - but with the correct port setting it works ;) thanks for your help!

@mgk89 Glad you got it working! Just FYI I'm making some new updates right now which will include some a security feature and bug fixes, so keep an eye out for new commits in the near future :)