Skip to content

Commit

Permalink
Convert worker to ESM (#500)
Browse files Browse the repository at this point in the history
* Convert worker to ESM

To use ESM for the worker, I created a package.json file in worker/ with `{ type: "module" }` as its sole content.

I then rewrote every import to use ESM syntax.

I also tried to set `{ type: "module" }` in the root package.json file to also use ESM in next.config.js.

However, this resulted in a weird problem: default imports were now getting imported as objects in this shape: `{ default: <defaultImport> }`.

Afaik, this should only be the case if you use "import * as foo from 'bar'" syntax: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import#default_import

This is fixed by not using `{ type: "module" }` for some reason. However, then, next.config.js also doesn't support ESM import syntax anymore.

The documentation says that if you want to use ESM, you can use next.config.mjs: https://nextjs.org/docs/pages/api-reference/next-config-js

But I didn't want to use MJS extension since I don't have any experience with it. For example, not sure if it's good style to mix JS with MJS etc. So I kept the CJS import syntax there.

* Ignore worker/ during linting

I wasn't able to fix the following errors:

/home/runner/work/stacker.news/stacker.news/worker/auction.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/auction.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/earn.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/earn.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/index.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/index.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/nostr.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/nostr.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/ots.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/ots.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/repin.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/repin.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/search.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/search.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/streak.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/streak.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/trust.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/trust.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/views.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/views.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)
/home/runner/work/stacker.news/stacker.news/worker/wallet.js:0:0: Parsing error: No Babel config file detected for /home/runner/work/stacker.news/stacker.news/worker/wallet.js. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files. (null)

I tried to tell babel where to find the babel config file (.babelrc), specifying the babel config in worker/package.json under "babel", using babel.config.json etc. to no avail.

However, afaict, we don't need babel for the worker since it won't run in a browser. Babel is only used to transpile code to target browsers.

But it still would be nice to lint the worker code with standard.

But we can figure this out later.

* Fix worker imports from lib/ and api/

This fixes the issue that we can't use `{ "type": "module" }` in the root package.json since it breaks the app with this error:

  app  | TypeError: next_auth_providers_credentials__WEBPACK_IMPORTED_MODULE_2__ is not a function
  app  |     at eval (webpack-internal:///./pages/api/auth/[...nextauth].js:218:20)
  app  |     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
  app  | LND GRPC connection successful
  app  | - error pages/api/auth/[...nextauth].js (139:2) @ CredentialsProvider
  app  | - error Error [TypeError]: next_auth_providers_credentials__WEBPACK_IMPORTED_MODULE_2__ is not a function
  app  |     at eval (webpack-internal:///./pages/api/auth/[...nextauth].js:218:20) {
  app  |   digest: undefined
  app  | }
  app  |   137 |
  app  |   138 | const providers = [
  app  | > 139 |   CredentialsProvider({
  app  |       |  ^
  app  |   140 |     id: 'lightning',
  app  |   141 |     name: 'Lightning',
  app  |   142 |     credentials: {
  app  | TypeError: next_auth_providers_credentials__WEBPACK_IMPORTED_MODULE_2__ is not a function
  app  |     at eval (webpack-internal:///./pages/api/auth/[...nextauth].js:218:20)
  app  |     at process.processTicksAndRejections (node:internal/process/task_queues:95:5)

build but we need to tell the worker that the files are MJS, else we get this error:

  worker  | file:///app/worker/wallet.js:3
  worker  | import { datePivot } from '../lib/time.js'
  worker  |          ^^^^^^^^^
  worker  | SyntaxError: Named export 'datePivot' not found. The requested module '../lib/time.js' is a CommonJS module, which may not support all module.exports as named exports.
  worker  | CommonJS modules can always be imported via the default export, for example using:
  worker  |
  worker  | import pkg from '../lib/time.js';
  worker  | const { datePivot } = pkg;
  worker  |
  worker  |     at ModuleJob._instantiate (node:internal/modules/esm/module_job:124:21)
  worker  |     at async ModuleJob.run (node:internal/modules/esm/module_job:190:5)
  worker  |
  worker  | Node.js v18.17.0
  worker  |
  worker exited with code 1

* Fix global not defined in browser context

* Also ignore api/ and lib/ during linting

I did not want to do this but I was not able to fix this error in any other way I tried:

  /home/ekzyis/programming/stacker.news/api/lnd/index.js:0:0: Parsing error: No Babel config file detected for /home/ekzyis/programming/stacker.news/api/lnd/index.js. Either disable config file checking with requ
ireConfigFile: false, or configure Babel so that it can find the config files. (null)

Did not want to look deeper into all this standard, eslint, babel configuration stuff ...

---------

Co-authored-by: ekzyis <ek@stacker.news>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
  • Loading branch information
3 people committed Sep 24, 2023
1 parent d60a589 commit dde82e2
Show file tree
Hide file tree
Showing 23 changed files with 229 additions and 243 deletions.
3 changes: 3 additions & 0 deletions api/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
8 changes: 4 additions & 4 deletions api/resolvers/serial.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { GraphQLError } = require('graphql')
const retry = require('async-retry')
const Prisma = require('@prisma/client')
import { GraphQLError } from 'graphql'
import retry from 'async-retry'
import Prisma from '@prisma/client'

async function serialize (models, ...calls) {
return await retry(async bail => {
Expand Down Expand Up @@ -56,4 +56,4 @@ async function serialize (models, ...calls) {
})
}

module.exports = serialize
export default serialize
4 changes: 2 additions & 2 deletions api/search/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const os = require('@opensearch-project/opensearch')
import os from '@opensearch-project/opensearch'

const options = process.env.NODE_ENV === 'development'
? { node: 'http://localhost:9200' }
Expand All @@ -12,4 +12,4 @@ const options = process.env.NODE_ENV === 'development'

global.os = global.os || new os.Client(options)

module.exports = global.os
export default global.os
4 changes: 2 additions & 2 deletions lib/apollo.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ export default function getApolloClient () {
if (SSR) {
return getClient(`${process.env.SELF_URL}/api/graphql`)
} else {
global.apolloClient ||= getClient('/api/graphql')
return global.apolloClient
window.apolloClient ||= getClient('/api/graphql')
return window.apolloClient
}
}

Expand Down
102 changes: 49 additions & 53 deletions lib/constants.js
Original file line number Diff line number Diff line change
@@ -1,57 +1,53 @@
// XXX this is temporary until we have so many subs they have
// to be loaded from the server
const SUBS = ['bitcoin', 'nostr', 'tech', 'meta', 'jobs']
const SUBS_NO_JOBS = SUBS.filter(s => s !== 'jobs')
export const SUBS = ['bitcoin', 'nostr', 'tech', 'meta', 'jobs']
export const SUBS_NO_JOBS = SUBS.filter(s => s !== 'jobs')

module.exports = {
NOFOLLOW_LIMIT: 100,
BOOST_MIN: 5000,
UPLOAD_SIZE_MAX: 2 * 1024 * 1024,
IMAGE_PIXELS_MAX: 35000000,
UPLOAD_TYPES_ALLOW: [
'image/gif',
'image/heic',
'image/png',
'image/jpeg',
'image/webp'
],
COMMENT_DEPTH_LIMIT: 10,
MAX_TITLE_LENGTH: 80,
MAX_POLL_CHOICE_LENGTH: 30,
ITEM_SPAM_INTERVAL: '10m',
ANON_ITEM_SPAM_INTERVAL: '0',
INV_PENDING_LIMIT: 10,
BALANCE_LIMIT_MSATS: 1000000000, // 1m sats
ANON_INV_PENDING_LIMIT: 100,
ANON_BALANCE_LIMIT_MSATS: 0, // disable
MAX_POLL_NUM_CHOICES: 10,
MIN_POLL_NUM_CHOICES: 2,
POLL_COST: 1,
ITEM_FILTER_THRESHOLD: 1.2,
DONT_LIKE_THIS_COST: 1,
COMMENT_TYPE_QUERY: ['comments', 'freebies', 'outlawed', 'borderland', 'all', 'bookmarks'],
SUBS,
SUBS_NO_JOBS,
USER_SORTS: ['stacked', 'spent', 'comments', 'posts', 'referrals'],
ITEM_SORTS: ['zaprank', 'comments', 'sats'],
WHENS: ['day', 'week', 'month', 'year', 'forever'],
ITEM_TYPES: context => {
const items = ['all', 'posts', 'comments', 'bounties', 'links', 'discussions', 'polls']
if (!context) {
items.push('bios', 'jobs')
}
items.push('freebies')
if (context === 'user') {
items.push('jobs', 'bookmarks')
}
return items
},
OLD_ITEM_DAYS: 3,
ANON_USER_ID: 27,
AD_USER_ID: 9,
ANON_POST_FEE: 1000,
ANON_COMMENT_FEE: 100,
SSR: typeof window === 'undefined',
MAX_FORWARDS: 5,
LNURLP_COMMENT_MAX_LENGTH: 1000
export const NOFOLLOW_LIMIT = 100
export const BOOST_MIN = 5000
export const UPLOAD_SIZE_MAX = 2 * 1024 * 1024
export const IMAGE_PIXELS_MAX = 35000000
export const UPLOAD_TYPES_ALLOW = [
'image/gif',
'image/heic',
'image/png',
'image/jpeg',
'image/webp'
]
export const COMMENT_DEPTH_LIMIT = 10
export const MAX_TITLE_LENGTH = 80
export const MAX_POLL_CHOICE_LENGTH = 30
export const ITEM_SPAM_INTERVAL = '10m'
export const ANON_ITEM_SPAM_INTERVAL = '0'
export const INV_PENDING_LIMIT = 10
export const BALANCE_LIMIT_MSATS = 1000000000 // 1m sat
export const ANON_INV_PENDING_LIMIT = 100
export const ANON_BALANCE_LIMIT_MSATS = 0 // disabl
export const MAX_POLL_NUM_CHOICES = 10
export const MIN_POLL_NUM_CHOICES = 2
export const POLL_COST = 1
export const ITEM_FILTER_THRESHOLD = 1.2
export const DONT_LIKE_THIS_COST = 1
export const COMMENT_TYPE_QUERY = ['comments', 'freebies', 'outlawed', 'borderland', 'all', 'bookmarks']
export const USER_SORTS = ['stacked', 'spent', 'comments', 'posts', 'referrals']
export const ITEM_SORTS = ['zaprank', 'comments', 'sats']
export const WHENS = ['day', 'week', 'month', 'year', 'forever']
export const ITEM_TYPES = context => {
const items = ['all', 'posts', 'comments', 'bounties', 'links', 'discussions', 'polls']
if (!context) {
items.push('bios', 'jobs')
}
items.push('freebies')
if (context === 'user') {
items.push('jobs', 'bookmarks')
}
return items
}
export const OLD_ITEM_DAYS = 3
export const ANON_USER_ID = 27
export const AD_USER_ID = 9
export const ANON_POST_FEE = 1000
export const ANON_COMMENT_FEE = 100
export const SSR = typeof window === 'undefined'
export const MAX_FORWARDS = 5
export const LNURLP_COMMENT_MAX_LENGTH = 1000
3 changes: 3 additions & 0 deletions lib/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}
12 changes: 5 additions & 7 deletions lib/time.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function timeSince (timeStamp) {
export function timeSince (timeStamp) {
const now = new Date()
const secondsPast = (now.getTime() - timeStamp) / 1000
if (secondsPast < 60) {
Expand All @@ -20,7 +20,7 @@ function timeSince (timeStamp) {
return 'now'
}

function datePivot (date,
export function datePivot (date,
{ years = 0, months = 0, days = 0, hours = 0, minutes = 0, seconds = 0, milliseconds = 0 }) {
return new Date(
date.getFullYear() + years,
Expand All @@ -33,9 +33,9 @@ function datePivot (date,
)
}

const dayMonthYear = when => new Date(when).toISOString().slice(0, 10)
export const dayMonthYear = when => new Date(when).toISOString().slice(0, 10)

function timeLeft (timeStamp) {
export function timeLeft (timeStamp) {
const now = new Date()
const secondsPast = (timeStamp - now.getTime()) / 1000

Expand All @@ -57,6 +57,4 @@ function timeLeft (timeStamp) {
}
}

const sleep = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms))

module.exports = { timeSince, dayMonthYear, datePivot, timeLeft, sleep }
export const sleep = (ms) => new Promise((resolve, reject) => setTimeout(resolve, ms))
2 changes: 1 addition & 1 deletion next.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
const { withPlausibleProxy } = require('next-plausible')
const { InjectManifest } = require('workbox-webpack-plugin')
const { generatePrecacheManifest } = require('./sw/build')
const { generatePrecacheManifest } = require('./sw/build.js')

const isProd = process.env.NODE_ENV === 'production'
const corsHeaders = [
Expand Down
7 changes: 5 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,10 @@
"next"
],
"ignore": [
"**/spawn"
"**/spawn",
"**/worker",
"**/api",
"**/lib"
]
},
"devDependencies": {
Expand All @@ -114,4 +117,4 @@
"eslint": "^8.47.0",
"standard": "^17.1.0"
}
}
}
6 changes: 2 additions & 4 deletions pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import '../styles/globals.scss'
import { ApolloProvider, gql } from '@apollo/client'
import { MeProvider } from '../components/me'
import PlausibleProvider from 'next-plausible'
import getApolloClient from '../lib/apollo'
import getApolloClient from '../lib/apollo.js'
import { PriceProvider } from '../components/price'
import { BlockHeightProvider } from '../components/block-height'
import Head from 'next/head'
Expand Down Expand Up @@ -34,7 +34,7 @@ function writeQuery (client, apollo, data) {
}
}

function MyApp ({ Component, pageProps: { ...props } }) {
export default function MyApp ({ Component, pageProps: { ...props } }) {
const client = getApolloClient()
const router = useRouter()

Expand Down Expand Up @@ -111,5 +111,3 @@ function MyApp ({ Component, pageProps: { ...props } }) {
</>
)
}

export default MyApp
Loading

0 comments on commit dde82e2

Please sign in to comment.