diff --git a/Dockerfile b/Dockerfile index 828be842..7a715670 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,6 +46,9 @@ ADD ormconfig.js ormconfig.js ADD bower_components bower_components ADD sandbox sandbox +# Keep all storage user may want to persist in a distinct directory +RUN mkdir -p /persist/docs + # Set some default environment variables to give a setup that works out of the box when # started as: # docker run -p 8484:8484 -it @@ -53,7 +56,9 @@ ADD sandbox sandbox ENV GRIST_ORG_IN_PATH=true ENV GRIST_HOST=0.0.0.0 ENV APP_HOME_URL=http://localhost:8484 -ENV GRIST_DATA_DIR=docs -RUN mkdir -p docs +ENV APP_DOC_URL=http://localhost:8484 +ENV GRIST_DATA_DIR=/persist/docs +ENV GRIST_SESSION_COOKIE=grist_core +ENV TYPEORM_DATABASE=/persist/home.sqlite3 EXPOSE 8484 CMD npm run start:prod diff --git a/README.md b/README.md index 1d59dfb5..83115cab 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,34 @@ robustness of a database to organize your data and make you more productive. > :warning: This repository is in a pre-release state. Its release will be announced when it has all the planned components, and a solid independent build and test set-up. Currently, stand-alone -server functionality is present. Release of our web client is planned, along with an extensive -test suite. +server functionality is present, along with a single-user web client. This repository, [grist-core](https://github.com/gristlabs/grist-core), is maintained by Grist Labs. Our flagship product, available at https://www.getgrist.com, is built from the code you see here, combined with business-specific software designed to scale it to many users, handle billing, etc. +## Opening and editing a Grist document locally + +The easiest way to use Grist locally is with [Docker](https://www.docker.com/get-started). +From a terminal, do: + +```sh +docker pull gristlabs/grist +docker run -p 8484:8484 -it gristlabs/grist +``` + +Then visit `http://localhost:8484` in your browser. You'll be able to create and edit documents, +and to import documents downloaded from the https://docs.getgrist.com host. You'll also be able +to use the Grist API. + +To preserve your work across docker runs, provide a directory to save it in: + +```sh +docker pull gristlabs/grist +docker run -p 8484:8484 -v $PWD/persist:/persist -it gristlabs/grist +``` + ## Why Open Source? By opening its source code and offering an [OSI](https://opensource.org/)-approved free license, @@ -38,25 +58,22 @@ Grist benefits its users: include Grist in your pipeline. And if a feature is missing, you can just take the source code and build on top of it! -## How do I start? - -For building from source, you can start with this: - - npm install - npm run build:prod - npm run install:python - npm start - # unauthenticated grist api available at http://localhost:8484/api/ +## Building from source -Then you can use the Grist API locally to work on a document. Currently you need -to "upload" a document to work with it. This makes a copy of it that the server -controls - you can find it in the `data` directory: +Here are the steps needed: - curl -F 'upload=@YourDocument.grist' http://localhost:8484/api/docs - # Note the document ID that is returned. +```sh +npm install +npm run build:prod +npm run install:python +npm start +# unauthenticated grist client available at http://localhost:8484 +# unauthenticated grist api available at http://localhost:8484/api/ +``` -The [Data-Tables endpoints](https://support.getgrist.com/api/#tag/Data-Tables) are -particularly useful. +Then you can use the Grist client, or the API. You cannot (yet) edit Grist documents +in place on your file system. All imported/created documents will appear in the `docs` +subdirectory. For using hosted Grist, just head on over to . diff --git a/app/server/lib/FlexServer.ts b/app/server/lib/FlexServer.ts index 2073b27b..22b23b47 100644 --- a/app/server/lib/FlexServer.ts +++ b/app/server/lib/FlexServer.ts @@ -222,6 +222,7 @@ export class FlexServer implements GristServer { public addLogging() { if (this._check('logging')) { return; } + if (process.env.GRIST_LOG_SKIP_HTTP) { return; } // Add a timestamp token that matches exactly the formatting of non-morgan logs. morganLogger.token('logTime', (req: Request) => log.timestamp()); // Add an optional gristInfo token that can replace the url, if the url is sensitive @@ -335,7 +336,7 @@ export class FlexServer implements GristServer { // Allow static files to be requested from any origin. const options: serveStatic.ServeStaticOptions = { setHeaders: (res, filepath, stat) => { - res.header("Access-Control-Allow-Origin", "*"); + res.setHeader("Access-Control-Allow-Origin", "*"); } }; // Grist has static help files, which may be useful for standalone app, @@ -385,7 +386,14 @@ export class FlexServer implements GristServer { this.dbManager.setPrefix(process.env.GRIST_ID_PREFIX || ""); await this.dbManager.connect(); await this.dbManager.initializeSpecialIds(); - + // If working without a login system, make sure default user exists. + if (process.env.GRIST_DEFAULT_EMAIL) { + const profile: UserProfile = { + name: 'You', + email: process.env.GRIST_DEFAULT_EMAIL, + }; + await this.dbManager.getUserByLoginWithRetry(profile.email, profile); + } // Report which database we are using, without sensitive credentials. this.info.push(['database', getDatabaseUrl(this.dbManager.connection.options, false)]); } diff --git a/app/server/lib/log.ts b/app/server/lib/log.ts index 11019ec6..b3f9e766 100644 --- a/app/server/lib/log.ts +++ b/app/server/lib/log.ts @@ -64,7 +64,7 @@ function timestamp() { const fileTransportOptions = { stream: process.stderr, - level: 'debug', + level: process.env.GRIST_LOG_LEVEL || 'debug', timestamp: log.timestamp, colorize: true, json: process.env.GRIST_HOSTED_VERSION ? true : false diff --git a/package.json b/package.json index 3da9c105..3a90d6d8 100644 --- a/package.json +++ b/package.json @@ -1,16 +1,26 @@ { "name": "grist-core", - "version": "1.0.0", - "description": "", - "main": "index.js", + "version": "0.7.1", + "license": "Apache-2.0", + "description": "Grist is the evolution of spreadsheets", + "homepage": "https://github.com/gristlabs/grist-core", + "repository": "git://github.com/gristlabs/grist-core.git", "scripts": { "start": "tsc --build -w --preserveWatchOutput & catw app/client/*.css app/client/*/*.css -o static/bundle.css -v & webpack --config buildtools/webpack.config.js --mode development --watch --hide-modules & NODE_PATH=_build:_build/stubs nodemon -w _build/app/server -w _build/app/common _build/stubs/app/server/server.js & wait", "install:python": "buildtools/prepare_python.sh", "build:prod": "tsc --build && webpack --config buildtools/webpack.config.js --mode production && cat app/client/*.css app/client/*/*.css > static/bundle.css", "start:prod": "NODE_PATH=_build:_build/stubs node _build/stubs/app/server/server.js" }, - "keywords": [], - "author": "", + "keywords": [ + "grist", + "spreadsheet", + "database" + ], + "author": { + "name": "Grist Labs Inc.", + "email": "info@getgrist.com" + }, + "private": false, "devDependencies": { "@types/backbone": "1.3.43", "@types/content-disposition": "0.5.2", diff --git a/stubs/app/server/server.ts b/stubs/app/server/server.ts index 80a513a7..e07ed77b 100644 --- a/stubs/app/server/server.ts +++ b/stubs/app/server/server.ts @@ -4,6 +4,16 @@ * By default, starts up on port 8484. */ +// Set log levels before importing anything. +if (!process.env.DEBUG) { + // Be a lot less noisy by default. + setDefaultEnv('GRIST_LOG_LEVEL', 'error'); + setDefaultEnv('GRIST_LOG_SKIP_HTTP', 'true'); +} + +// Use a distinct cookie. +setDefaultEnv('GRIST_SESSION_COOKIE', 'grist_core'); + import {updateDb} from 'app/server/lib/dbUtils'; import {main as mergedServerMain} from 'app/server/mergedServerMain'; import * as fse from 'fs-extra'; @@ -19,13 +29,18 @@ function setDefaultEnv(name: string, value: string) { } } +// tslint:disable:no-console export async function main() { - // Use a distinct cookie. - setDefaultEnv('GRIST_SESSION_COOKIE', 'grist_core'); + console.log('Welcome to Grist.'); + if (!process.env.DEBUG) { + console.log(`In quiet mode, see http://localhost:${G.port} to use.`); + console.log('For full logs, re-run with DEBUG=1'); + } + // There's no login system released yet, so set a default email address. - setDefaultEnv('GRIST_DEFAULT_EMAIL', 'support@getgrist.com'); + setDefaultEnv('GRIST_DEFAULT_EMAIL', 'you@example.com'); // Set directory for uploaded documents. - setDefaultEnv('GRIST_DATA_DIR', 'data'); + setDefaultEnv('GRIST_DATA_DIR', 'docs'); await fse.mkdirp(process.env.GRIST_DATA_DIR!); // Make a blank db if needed. await updateDb(); @@ -34,6 +49,5 @@ export async function main() { } if (require.main === module) { - // tslint:disable-next-line:no-console main().catch((err) => console.error(err)); }