Commit d4ffcc7f authored by Aral Balkan's avatar Aral Balkan
Browse files

Merge branch 'sync-improvements'

parents 223e9927 5619edf8
......@@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](, and this project adheres to [Semantic Versioning](
## [16.1.0] - 2021-03-11
## Fixed
- Regression: `--sync-to` without `--sync-from` no longer fails (
## Improved
- The addition of a generated folder now causes the server to restart. So, for example, if you’re going from a plain site to a Hugo site and you sync, you do not need to manually restart your production server. (
- Sync now detects common erroneous invocations from well-known site subfolders (e.g., .hugo, .dynamic, etc.) and magically fixes the path (just like the serve command does for the path to serve). (
## [16.0.6] - 2021-03-08
Update to @small-tech/https version 2.1.2, which includes @small-tech/auto-encrypt version 2.2.0.
......@@ -403,6 +403,8 @@ The above command will result in the following directory structure on the remote
(As of 15.4.0) If the sync command cannot connect in 5 seconds, it will time out. If this happens, check that you have the correct host and account details specified. If you do, there might be a problem with your connection.
(As of 16.1.0) It’s a common mistake to start the sync without specifying the `--sync-from` option when not in the root of your site but in one of the well-known subfolders (e.g., `.hugo` if you’re working on a Hugo site or your `.dynamic` folder if you happen to be in it because you’re working on a site that uses DotJS.) In these instances, Site.js will detect the mistake and understand that you want to sync the site, not the subfolder and behave accordingly. If you _really_ want to sync one of the well-known subfolders for some reason, then specifically specify it by setting `--sync-from=.`. Note that this magic rewriting of the sync path doesn’t happen any time you specify a folder explicitly using the `--sync-from` option.
#### Live Sync
With the Live Sync feature, you can have Site.js watch for changes to your content and sync them to your server in real-time (e.g., if you want to live blog something or want to keep a page updated with local data you’re collecting from a sensor).
......@@ -1652,7 +1654,7 @@ We exist in part thanks to patronage by people like you. If you share [our visio
## Copyright
© 2019-2020 [Aral Balkan](, [Small Technology Foundation](
© 2019-2021 [Aral Balkan](, [Small Technology Foundation](
Let’s Encrypt is a trademark of the Internet Security Research Group (ISRG). All rights reserved. Node.js is a trademark of Joyent, Inc. and is used with its permission. We are not endorsed by or affiliated with Joyent or ISRG.
......@@ -319,7 +319,22 @@ function localFolder (args) {
let localFolder = null
// If --sync-from is not specified, we default to the path to be served (or use a default path).
const syncFrom = args.named[SYNC_FROM] || path || '.'
const dotWasSpecificallyRequestedForSyncFrom = (args.named[SYNC_FROM] === '.')
let syncFrom = args.named[SYNC_FROM] || path || '.'
// A common mistake is to start a sync from the .hugo, .dynamic, etc. folder
// because you happen to be working in it. Try to detect this and magically fix it.
if (!dotWasSpecificallyRequestedForSyncFrom && syncFrom === '.') {
let absoluteSyncPath = pathModule.resolve(syncFrom)
const specialFolders = /\.dynamic.*$|\.hugo.*$|\.db.*$|\.wildcard.*$/
const intelligentSyncPath = absoluteSyncPath.replace(specialFolders, '')
if (absoluteSyncPath !== intelligentSyncPath) {
syncFrom = pathModule.relative(absoluteSyncPath, intelligentSyncPath)
console.log(` 🧙 ❨site.js❩ ${clr('Magically changed sync path to the site root.', 'yellow')}`)
const syncFromEndsWithPathSeparator = syncFrom.endsWith(pathModule.sep)
// Handle the sync-folder-and-contents flag or its lack
......@@ -377,7 +392,7 @@ function remoteConnectionInfo (args) {
function defaultRemotePath (account) {
const localFolderPath = pathModule.resolve(syncFrom || path)
const localFolderPath = pathModule.resolve(syncFrom || path || pathModule.dirname('.'))
const localFolderFragments = localFolderPath.split(pathModule.sep)
const localFolderName = localFolderFragments[localFolderFragments.length-1]
......@@ -1200,11 +1200,15 @@ class Site {
const roots = []
// Serve any generated static content (e.g., Hugo output) that might exist.
const generatedStaticFilesDirectory = path.join(this.pathToServe, '.generated')
if (fs.existsSync(generatedStaticFilesDirectory)) {
this.generatedStaticFilesDirectory = path.join(this.pathToServe, '.generated')
this.generatedContentExists = fs.existsSync(this.generatedStaticFilesDirectory)
if (this.generatedContentExists) {
this.log(` 🎠 ❨site.js❩ Serving generated static files.`)
// Add the regular static web root.
......@@ -1319,6 +1323,13 @@ class Site {
this.log(` 🐁 ❨site.js❩ Wildcard route change: ${clr(`${this.prettyFileWatcherEvent(event)}`, 'green')} (${clr(file, 'cyan')}).`)
this.log('\n 🐁 ❨site.js❩ Requesting restart…\n')
await this.restartServer()
} else if (file.includes('/.generated') && !this.generatedContentExists && fs.existsSync(this.generatedStaticFilesDirectory)) {
// Generated folder has been added.
this.log(` 🐁 ❨site.js❩ Generated folder has been added: ${clr(`${this.prettyFileWatcherEvent(event)}`, 'green')} (${clr(file, 'cyan')}).`)
this.log('\n 🐁 ❨site.js❩ Requesting restart…\n')
await this.restartServer()
......@@ -56,7 +56,7 @@ class Util {
// Only attempt to magically fix the path to serve (if necessary)
// if the current directory way not specifically requested by the person.
// if the current directory was not specifically requested by the person.
let absolutePathToServe = path.resolve(pathToServe)
if (pathSpecified !== '.' && pathToServe === '.') {
"name": "@small-tech/site.js",
"version": "16.0.6",
"version": "16.1.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"name": "@small-tech/site.js",
"version": "16.0.6",
"version": "16.1.0",
"description": "Small Web construction set.",
"keywords": [
"web server",
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment