-
Notifications
You must be signed in to change notification settings - Fork 6
Content Indexer #337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Content Indexer #337
Changes from all commits
5d01c24
2cf9947
bb8fef9
a60f089
2ea88db
968e0eb
19c2a04
be0a04e
d6d00d7
453407a
c435076
13c4256
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,4 +2,5 @@ node_modules | |
| .next | ||
| out | ||
| public | ||
| bak | ||
| bak | ||
| src/db/server/* | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |
| } | ||
| ] | ||
| }, | ||
|
|
||
| "parser": "@typescript-eslint/parser", | ||
| "overrides": [ | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -32,13 +32,18 @@ | |
| "clean": "rm -rf .next", | ||
| "dev": "next dev", | ||
| "build": "next build", | ||
| "prebuild-index": "bash scripts/run-indexer.sh -P 20123", | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need some docs on how to run
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK, pre- and post- tasks are run automatically. |
||
| "build-index": "env ML_INDEX_CONTENT=true ML_DB_API_PORT=20123 next build", | ||
| "postbuild-index": "bash scripts/dump-and-stop-indexer.sh -O public/full-db.json -P 20123", | ||
| "build:sitemap": "next-sitemap", | ||
| "start": "next start", | ||
| "lint": "eslint . -f codeframe", | ||
| "prettier:check": "npx prettier --config .prettierrc --ignore-path .prettierignore --check src", | ||
| "test:e2e": "playwright test", | ||
| "test:unit": "vitest __tests__", | ||
| "test:unit:ci": "vitest __tests__ --reporter=junit --outputFile.junit=unit-tests-results.xml" | ||
| "test:unit:ci": "vitest __tests__ --reporter=junit --outputFile.junit=unit-tests-results.xml", | ||
| "dev-index": "next dev", | ||
| "predev-index": "bash scripts/run-indexer.sh" | ||
| }, | ||
| "dependencies": { | ||
| "@radix-ui/react-icons": "^1.1.1", | ||
|
|
@@ -61,6 +66,9 @@ | |
| "react-copy-to-clipboard": "^5.1.0", | ||
| "react-dom": "18.2.0", | ||
| "react-google-recaptcha": "^2.1.0", | ||
| "rimraf": "^3.0.2", | ||
| "rxdb": "^14.1.8", | ||
| "rxjs": "^7.8.0", | ||
| "tmp": "^0.2.1" | ||
| }, | ||
| "devDependencies": { | ||
|
|
@@ -76,6 +84,7 @@ | |
| "@types/js-cookie": "^3.0.2", | ||
| "@types/react": "^18.0.26", | ||
| "@types/react-google-recaptcha": "^2.1.5", | ||
| "@types/rimraf": "^3.0.2", | ||
| "@types/tmp": "^0.2.3", | ||
| "@typescript-eslint/eslint-plugin": "^5.45.1", | ||
| "@typescript-eslint/parser": "^5.45.1", | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {"schemas":[{"articles":{"schema":{"version":0,"title":"Schema for ML Articles","keyCompression":false,"primaryKey":"url","type":"object","properties":{"url":{"type":"string","maxLength":100},"labels":{"type":"array","items":{"type":"string"}},"startDate":{"type":"number"},"endDate":{"type":"number"},"locales":{"type":"array","items":{"type":"string"}}},"required":["url","labels","locales","startDate"]}}}],"data":{"name":"ml","instanceToken":"morvycskkp","collections":[{"name":"articles","schemaHash":"dyk9bi","docs":[{"url":"about","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718891.07},"_deleted":false},{"url":"contribute","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718931.02},"_deleted":false},{"url":"docs","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718594.01},"_deleted":false},{"url":"docs/the-story-of-mel","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718600.01},"_deleted":false},{"url":"docs/the-story-of-mel/codex","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718642.07},"_deleted":false},{"url":"docs/the-story-of-mel/pages/blackjack-writeup","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134716878.01},"_deleted":false},{"url":"docs/the-story-of-mel/pages/mels-hack-the-missing-bits","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134717242.01},"_deleted":false},{"url":"docs/the-story-of-mel/pages/preface","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134717372.02},"_deleted":false},{"url":"docs/the-story-of-mel/pages/resources","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134717399.06},"_deleted":false},{"url":"glossary","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718608.05},"_deleted":false},{"url":"glossary/addressing-scheme","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718640.01},"_deleted":false},{"url":"glossary/assembly-language","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718645.07},"_deleted":false},{"url":"glossary/bit","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718649.07},"_deleted":false},{"url":"glossary/compiler","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718654.07},"_deleted":false},{"url":"glossary/drum-memory","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718666.01},"_deleted":false},{"url":"glossary/fortran","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718670.06},"_deleted":false},{"url":"glossary/friden-flexowriter","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718682.07},"_deleted":false},{"url":"glossary/goto","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718686.07},"_deleted":false},{"url":"glossary/hexadecimal","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718691.07},"_deleted":false},{"url":"glossary/infinite-loop","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718695.01},"_deleted":false},{"url":"glossary/jump-instruction","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718701.07},"_deleted":false},{"url":"glossary/lgp-30","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718705.07},"_deleted":false},{"url":"glossary/loop","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718709.07},"_deleted":false},{"url":"glossary/machine-code","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718713.07},"_deleted":false},{"url":"glossary/magnetic-core-memory","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718722.07},"_deleted":false},{"url":"glossary/operand","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718728.02},"_deleted":false},{"url":"glossary/operation-code","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718734.07},"_deleted":false},{"url":"glossary/optimal-code","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718739.01},"_deleted":false},{"url":"glossary/optimum","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718743.01},"_deleted":false},{"url":"glossary/pascal","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718748.03},"_deleted":false},{"url":"glossary/pessimum","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718762.02},"_deleted":false},{"url":"glossary/port","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718772.04},"_deleted":false},{"url":"glossary/ratfor","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718776.07},"_deleted":false},{"url":"glossary/real-programmer","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718785.01},"_deleted":false},{"url":"glossary/register","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718788.07},"_deleted":false},{"url":"glossary/rpc-4000","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718804.02},"_deleted":false},{"url":"glossary/terminating-condition","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718809.01},"_deleted":false},{"url":"glossary/test-terminating-condition","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718817.07},"_deleted":false},{"url":"glossary/time-delay-loop","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718821.01},"_deleted":false},{"url":"glossary/top-down-design","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718823.07},"_deleted":false},{"url":"glossary/vacuum-tube","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718836.07},"_deleted":false},{"url":"posts/07-04-21-hebrew-edition","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718954.06},"_deleted":false},{"url":"posts/14-01-21-here-we-go","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718958.02},"_deleted":false},{"url":"posts/21-05-22-project-launch","labels":[],"locales":["en","he"],"_meta":{"lwt":1678134718961.07},"_deleted":false}]}]}} | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NICE! |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| #!/bin/bash | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Need docs on how to run
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (see below) |
||
|
|
||
| OUTFILE="" | ||
| DB_PORT="" | ||
| USAGE="Usage: $( basename $0 ) -O </full/out/file/path> -P <port of DB server>" | ||
|
|
||
| shopt -s nocasematch | ||
| while (( "$#" )); do | ||
| nextarg=$1 | ||
| shift | ||
| case $nextarg in | ||
| "-O"|"--outfile") | ||
| OUTFILE="$1" | ||
| shift | ||
| ;; | ||
| "-P"|"--port") | ||
| DB_PORT="$1" | ||
| shift | ||
| ;; | ||
| *) | ||
| echo $USAGE | ||
| echo "unkonwn option $nextarg" >&2 | ||
| exit 1 | ||
| ;; | ||
| esac | ||
| done | ||
|
|
||
| if [ $DB_PORT == "" ] ; then | ||
| echo $USAGE >& 2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| if [ "$OUTFILE" == "" ]; then | ||
| echo $USAGE >& 2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| OUTPATH=`dirname "$OUTFILE"` | ||
| OUTFILE=`basename "$OUTFILE"` | ||
| # ensure out path exists | ||
| mkdir -p "$OUTPATH" | ||
|
|
||
| if [ ! -d "$OUTPATH" ]; then | ||
| echo "Failed to create folder $OUTPATH" | ||
| exit 1; | ||
| fi | ||
|
|
||
| DB_URL="http://localhost:${DB_PORT}" | ||
|
|
||
| # get full outfile path (param may be relative) | ||
| OUTPATH=$( cd "$OUTPATH" && pwd -P ) | ||
|
|
||
| ENCODED_PATH=$( node -p "encodeURIComponent('$OUTPATH/$OUTFILE')" ) | ||
|
|
||
| #dump db to file | ||
| curl "${DB_URL}/save/$ENCODED_PATH" | ||
| #and terminate the db server | ||
| curl ${DB_URL}/terminate | ||
|
|
||
| # Add the result to git | ||
| git add "$OUTPATH/$OUTFILE" | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| #!/bin/bash | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same, need docs on how to run
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @tomerlichtash
|
||
| # get dir of running script | ||
| SCRIPT_DIR=`dirname "$0"`; | ||
|
|
||
| DB_PORT="" | ||
| USAGE="Usage: $( basename $0 ) -P <port of DB server>" | ||
|
|
||
| shopt -s nocasematch | ||
| while (( "$#" )); do | ||
| nextarg=$1 | ||
| shift | ||
| case $nextarg in | ||
| "-P"|"--port") | ||
| DB_PORT="$1" | ||
| shift | ||
| ;; | ||
| *) | ||
| echo $USAGE | ||
| echo "unkonwn option $nextarg" >&2 | ||
| exit 1 | ||
| ;; | ||
| esac | ||
| done | ||
|
|
||
| if [ $DB_PORT == "" ] ; then | ||
| echo $USAGE >& 2 | ||
| exit 1 | ||
| fi | ||
|
|
||
| #move to a known folder | ||
| pushd "$SCRIPT_DIR" | ||
| #cd to db server | ||
| cd ../src/db/server | ||
| #run the server | ||
| node app.js --port=$DB_PORT & | ||
| # node app.js > /dev/null & | ||
| popd | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,23 +1,32 @@ | ||
| import React, { Context, createContext } from "react"; | ||
| import { createDBService } from "../db/client/client-db-service"; | ||
| import { IClientDBService } from "../interfaces/db-service.d"; | ||
| import { IDynamicContentServer } from "../interfaces/dynamic-content"; | ||
| import { IPageContext } from "../interfaces/page-context"; | ||
| import { DynamicContentServer } from "../lib/dynamic-content-server"; | ||
|
|
||
| export class PageContext implements IPageContext { | ||
| class PageContext implements IPageContext { | ||
| constructor( | ||
| public readonly dynamicContentServer: IDynamicContentServer, | ||
| public readonly dbService: IClientDBService, | ||
| public documentPath: string | ||
| ) {} | ||
| ) { | ||
| } | ||
| } | ||
|
|
||
| const ctx = createContext<IPageContext>(new PageContext(null, "")); | ||
| const ctx = createContext<IPageContext>(new PageContext(null, null, "")); | ||
|
|
||
| export const ReactPageContext: Context<IPageContext> = ctx; | ||
|
|
||
| export const PageContextProvider = ({ documentPath, children }) => ( | ||
| <ReactPageContext.Provider | ||
| value={new PageContext(new DynamicContentServer(), documentPath as string)} | ||
| > | ||
| {children} | ||
| </ReactPageContext.Provider> | ||
| ); | ||
| export const PageContextProvider = ({ documentPath, children }) => { | ||
| return ( | ||
| <ReactPageContext.Provider | ||
| value={new PageContext( | ||
| new DynamicContentServer(), | ||
| createDBService(), | ||
| documentPath as string)} | ||
| > | ||
| {children} | ||
| </ReactPageContext.Provider> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,101 @@ | ||
| /* eslint @typescript-eslint/no-explicit-any: 0 */ | ||
|
|
||
| // Some RxDB types are either complicated or obscure enough to justify | ||
| // casting some parameters as any | ||
|
|
||
| import { RxDBDevModePlugin } from 'rxdb/plugins/dev-mode'; | ||
| import { RxDBJsonDumpPlugin } from 'rxdb/plugins/json-dump'; | ||
| import { createRxDatabase, RxDatabase, addRxPlugin } from 'rxdb'; | ||
| import { getRxStorageMemory } from "rxdb/plugins/storage-memory"; | ||
|
|
||
| import { IClientDBService } from "../../interfaces/db-service.d"; | ||
| import { DB_SERVICE_MODELS } from "../models/index.d"; | ||
| import { importDBData } from '../common/db-utils'; | ||
| import { mlUtils } from '../../lib/ml-utils'; | ||
|
|
||
| enum DBStates { | ||
| None, Loading, Loaded, Error | ||
| } | ||
|
|
||
| class ClientDBService implements IClientDBService { | ||
| private _db: RxDatabase; | ||
| private _state = DBStates.None; | ||
|
|
||
| constructor() { | ||
| if (mlUtils.appEnvironment.isBrowser) { | ||
| addRxPlugin(RxDBDevModePlugin); | ||
| addRxPlugin(RxDBJsonDumpPlugin); | ||
| } | ||
| } | ||
|
|
||
| public async load(): Promise<string> { | ||
| if (this._state === DBStates.Loading) { | ||
| return"service already loading"; | ||
| } | ||
| if (this._state === DBStates.Loaded) { | ||
| return ""; | ||
| } | ||
| if (!mlUtils.appEnvironment.isBrowser) { | ||
| this._state = DBStates.Loaded; | ||
| return ""; | ||
| } | ||
| this._state = DBStates.Loading; | ||
| let error = ""; | ||
| try { | ||
| const url = `/full-db.json`; | ||
| const response = await fetch(url, { | ||
| method: "GET", | ||
| }); | ||
| const responseData = await response.json() as DB_SERVICE_MODELS.IDBDump; | ||
| if (responseData?.data && responseData.schemas) { | ||
| error = await this.createDB(responseData); | ||
| } | ||
| else { | ||
| error = "Failed to get or parse DB data"; | ||
| } | ||
| } | ||
| catch (e) { | ||
| error = String(e); | ||
| } | ||
| this._state = error ? DBStates.Error : DBStates.Loaded; | ||
|
|
||
| return error ? `Error initializing database ${error}` : ""; | ||
| } | ||
|
|
||
|
|
||
| private async createDB(dump: DB_SERVICE_MODELS.IDBDump): Promise<string> { | ||
| try { | ||
| const db = await createRxDatabase({ | ||
| name: "db-service", | ||
| storage: getRxStorageMemory() | ||
| }); | ||
| for (let schema of dump.schemas || []) { | ||
| // eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
| const added = await db.addCollections(schema as any); | ||
| console.log(added); | ||
| } | ||
| await importDBData( { db, dump, loadData: true }); | ||
| // const importData = this.processJSON(db, dump.data); | ||
| // // eslint-disable-next-line @typescript-eslint/no-unsafe-argument | ||
| // await db.importJSON(importData as any); | ||
| const all = await db.collections.articles.find().exec(); | ||
| console.log(all); | ||
|
|
||
| this._db = db; | ||
| return ""; | ||
| } | ||
| catch (e) { | ||
| return String(e); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| let globalDB: IClientDBService | null = null; | ||
|
|
||
| export const createDBService: () => IClientDBService = () => { | ||
| if (!globalDB) { | ||
| globalDB = new ClientDBService(); | ||
| } | ||
|
|
||
| return globalDB; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Need some docs on how to run
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nothing to document. If you have a reason to run the DB application in debug mode, use the DB App launch config, otherwise don't...