Convert worker to ESM (#500)
* 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>
2023-09-24 01:19:35 +00:00
|
|
|
import { gql } from 'graphql-tag'
|
|
|
|
import search from '../api/search/index.js'
|
|
|
|
import removeMd from 'remove-markdown'
|
2022-01-25 19:34:51 +00:00
|
|
|
|
|
|
|
const ITEM_SEARCH_FIELDS = gql`
|
|
|
|
fragment ItemSearchFields on Item {
|
|
|
|
id
|
|
|
|
parentId
|
|
|
|
createdAt
|
|
|
|
updatedAt
|
|
|
|
title
|
|
|
|
text
|
|
|
|
url
|
2022-01-27 19:18:48 +00:00
|
|
|
userId
|
2022-01-25 19:34:51 +00:00
|
|
|
user {
|
|
|
|
name
|
|
|
|
}
|
2022-02-17 17:23:43 +00:00
|
|
|
sub {
|
|
|
|
name
|
|
|
|
}
|
2023-07-23 15:08:43 +00:00
|
|
|
root {
|
|
|
|
subName
|
|
|
|
}
|
2022-02-26 16:41:30 +00:00
|
|
|
status
|
2022-02-17 17:23:43 +00:00
|
|
|
maxBid
|
2022-03-07 21:50:13 +00:00
|
|
|
company
|
|
|
|
location
|
|
|
|
remote
|
2022-01-25 19:34:51 +00:00
|
|
|
upvotes
|
|
|
|
sats
|
|
|
|
boost
|
2022-09-02 23:01:58 +00:00
|
|
|
lastCommentAt
|
|
|
|
commentSats
|
2022-01-28 19:19:56 +00:00
|
|
|
path
|
2022-01-25 19:34:51 +00:00
|
|
|
ncomments
|
|
|
|
}`
|
|
|
|
|
2023-11-21 23:26:24 +00:00
|
|
|
async function _indexItem (item, { models }) {
|
2022-01-25 19:34:51 +00:00
|
|
|
console.log('indexing item', item.id)
|
2022-03-07 21:50:13 +00:00
|
|
|
// HACK: modify the title for jobs so that company/location are searchable
|
|
|
|
// and highlighted without further modification
|
|
|
|
const itemcp = { ...item }
|
|
|
|
if (item.company) {
|
|
|
|
itemcp.title += ` \\ ${item.company}`
|
|
|
|
}
|
|
|
|
if (item.location || item.remote) {
|
|
|
|
itemcp.title += ` \\ ${item.location || ''}${item.location && item.remote ? ' or ' : ''}${item.remote ? 'Remote' : ''}`
|
|
|
|
}
|
2023-07-23 15:08:43 +00:00
|
|
|
if (!item.sub?.name && item.root?.subName) {
|
|
|
|
itemcp.sub = { name: item.root.subName }
|
|
|
|
}
|
2023-07-25 00:50:55 +00:00
|
|
|
if (item.text) {
|
|
|
|
itemcp.text = removeMd(item.text)
|
|
|
|
}
|
2022-03-07 21:50:13 +00:00
|
|
|
|
2023-11-21 23:26:24 +00:00
|
|
|
const itemdb = await models.item.findUnique({
|
|
|
|
where: { id: Number(item.id) },
|
|
|
|
select: { weightedVotes: true, weightedDownVotes: true }
|
|
|
|
})
|
|
|
|
|
|
|
|
itemcp.wvotes = itemdb.weightedVotes - itemdb.weightedDownVotes
|
|
|
|
|
2022-01-25 19:34:51 +00:00
|
|
|
try {
|
|
|
|
await search.index({
|
|
|
|
id: item.id,
|
|
|
|
index: 'item',
|
|
|
|
version: new Date(item.updatedAt).getTime(),
|
|
|
|
versionType: 'external_gte',
|
2022-03-07 21:50:13 +00:00
|
|
|
body: itemcp
|
2022-01-25 19:34:51 +00:00
|
|
|
})
|
|
|
|
} catch (e) {
|
|
|
|
// ignore version conflict ...
|
|
|
|
if (e?.meta?.statusCode === 409) {
|
|
|
|
console.log('version conflict ignoring', item.id)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
console.log(e)
|
|
|
|
throw e
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-21 23:32:22 +00:00
|
|
|
export async function indexItem ({ data: { id }, apollo, models }) {
|
|
|
|
// 1. grab item from database
|
|
|
|
// could use apollo to avoid duping logic
|
|
|
|
// when grabbing sats and user name, etc
|
|
|
|
const { data: { item } } = await apollo.query({
|
|
|
|
query: gql`
|
2022-01-25 19:34:51 +00:00
|
|
|
${ITEM_SEARCH_FIELDS}
|
|
|
|
query Item {
|
|
|
|
item(id: ${id}) {
|
|
|
|
...ItemSearchFields
|
|
|
|
}
|
|
|
|
}`
|
2023-11-21 23:32:22 +00:00
|
|
|
})
|
2022-01-25 19:34:51 +00:00
|
|
|
|
2023-11-21 23:32:22 +00:00
|
|
|
// 2. index it with external version based on updatedAt
|
|
|
|
await _indexItem(item, { models })
|
2022-01-25 19:34:51 +00:00
|
|
|
}
|
|
|
|
|
2023-11-21 23:32:22 +00:00
|
|
|
export async function indexAllItems ({ apollo, models }) {
|
|
|
|
// cursor over all items in the Item table
|
|
|
|
let items = []; let cursor = null
|
|
|
|
do {
|
|
|
|
// query for items
|
|
|
|
({ data: { items: { items, cursor } } } = await apollo.query({
|
|
|
|
query: gql`
|
2022-01-25 19:34:51 +00:00
|
|
|
${ITEM_SEARCH_FIELDS}
|
|
|
|
query AllItems($cursor: String) {
|
2023-11-09 00:15:36 +00:00
|
|
|
items(cursor: $cursor, sort: "recent", limit: 1000, type: "all") {
|
2022-01-25 19:34:51 +00:00
|
|
|
items {
|
|
|
|
...ItemSearchFields
|
|
|
|
}
|
|
|
|
cursor
|
|
|
|
}
|
|
|
|
}`,
|
2023-11-21 23:32:22 +00:00
|
|
|
variables: { cursor }
|
|
|
|
}))
|
2022-01-25 19:34:51 +00:00
|
|
|
|
2023-11-21 23:32:22 +00:00
|
|
|
// for all items, index them
|
|
|
|
try {
|
|
|
|
items.forEach(i => _indexItem(i, { models }))
|
|
|
|
} catch (e) {
|
|
|
|
// ignore errors
|
|
|
|
console.log(e)
|
|
|
|
}
|
|
|
|
} while (cursor)
|
2022-01-25 19:34:51 +00:00
|
|
|
}
|