Skip to content
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

refactor: generate sitemap and rss commands #137

Merged
merged 2 commits into from
Nov 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmd/generateMenu.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func RunGenerateMenuCmd(cmd *cobra.Command, args []string) {

// ADD FILE: config/menu.js
cfg.log.Info("Saving the menu.js.ts file")
menuFile := cfg.fsManager.NewMenuFile("menu", &cfg.prodData, allRoutes, contents, withContentFlag)
menuFile := cfg.fsManager.NewMenuFile("menu", allRoutes, contents, withContentFlag)
configFolder.Add(menuFile)

// SET FOLDER STRUCTURE
Expand Down
2 changes: 1 addition & 1 deletion cmd/generateRss.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func RunGenerateRSSCmd(cmd *cobra.Command, args []string) {

// NEW FILE: static/rss.xml
cfg.log.Info("Saving the file to the static folder")
rssFile := cfg.fsManager.NewNoPageFile("rss", &cfg.prodData, allRoutes, contents)
rssFile := cfg.fsManager.NewNoPageFile("rss", &cfg.projectSettings, allRoutes, contents)
staticFolder.Add(rssFile)

// SET FOLDER STRUCTURE
Expand Down
2 changes: 1 addition & 1 deletion cmd/generateSitemap.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ func RunGenerateSitemapCmd(cmd *cobra.Command, args []string) {

// NEW FILE: static/rss.xml
cfg.log.Info("Saving the file to the static folder")
sitemapFile := cfg.fsManager.NewNoPageFile("sitemap", &cfg.prodData, allRoutes, contents)
sitemapFile := cfg.fsManager.NewNoPageFile("sitemap", &cfg.projectSettings, allRoutes, contents)
staticFolder.Add(sitemapFile)

// SET FOLDER STRUCTURE
Expand Down
25 changes: 18 additions & 7 deletions cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,7 @@ func InitCmdRun(cmd *cobra.Command, args []string) {
envFile := cfg.fsManager.NewDotEnvFile(projectName, dotEnvTplData)

// NEW FILE: .sveltin.json
sveltinConfigTplData := &config.TemplateData{
Name: ProjectSettingsFile,
Misc: &tpltypes.MiscFileData{
Info: CliVersion,
},
Theme: themeData,
}
sveltinConfigTplData := newSveltinJsonTplData(projectName, themeData)
sveltinJSONConfigFile := cfg.fsManager.NewJSONConfigFile(sveltinConfigTplData)

// SET FOLDER STRUCTURE
Expand Down Expand Up @@ -430,7 +424,24 @@ func makeProjectFolderStructure(folderName string, projectName string, themeData
default:
err := errors.New("something went wrong: folder not found as mapped resource for sveltin projects")
return nil, sveltinerr.NewDefaultError(err)
}
}

func newSveltinJsonTplData(projectName string, themeData *tpltypes.ThemeData) *config.TemplateData {
return &config.TemplateData{
Name: ProjectSettingsFile,
ProjectSettings: &tpltypes.ProjectSettings{
Sveltin: tpltypes.SveltinCLIData{
Version: CliVersion,
},
Name: projectName,
BaseURL: fmt.Sprintf("http://%s.com", projectName),
Sitemap: tpltypes.SitemapData{
ChangeFreq: "monthly",
Priority: 0.5,
},
Theme: *themeData,
},
}
}

Expand Down
30 changes: 27 additions & 3 deletions cmd/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const (
ProjectSettingsMigrationID string = "projectSettings"
DefaultsConfigMigrationID string = "defaultsConfig"
ThemeConfigMigrationID string = "themeConfig"
DotEnvMigrationID string = "dotenv"
)

//=============================================================================
Expand Down Expand Up @@ -68,6 +69,12 @@ func RunUpgradeCmd(cmd *cobra.Command, args []string) {
err = updateThemeConfigMigration.Execute()
utils.ExitIfError(err)

// File: <project_root>/.env.production
pathToDotEnvFile := path.Join(cwd, DotEnvProdFile)
updateDotEnvMigration := handleMigration(DotEnvMigrationID, migrationManager, cfg, pathToDotEnvFile)
err = updateDotEnvMigration.Execute()
utils.ExitIfError(err)

cfg.log.Success(fmt.Sprintf("Your project is ready for sveltin v%s\n", CliVersion))
}

Expand All @@ -85,6 +92,8 @@ func handleMigration(migrationType string, migrationManager *migrations.Migratio
return newUpdateDefaultsConfigMigration(migrationManager, config, pathToFile)
case ThemeConfigMigrationID:
return newUpdateThemeConfigMigration(migrationManager, config, pathToFile)
case DotEnvMigrationID:
return newDotEnvMigration(migrationManager, config, pathToFile)
default:
return nil
}
Expand All @@ -100,7 +109,7 @@ func newAddProjectSettingsMigration(migrationManager *migrations.MigrationManage
Data: &migrations.MigrationData{
PathToFile: pathTofile,
CliVersion: CliVersion,
ProjectCliVersion: config.projectSettings.CLI.Version,
ProjectCliVersion: config.projectSettings.Sveltin.Version,
},
}
}
Expand All @@ -115,7 +124,7 @@ func newUpdateDefaultsConfigMigration(migrationManager *migrations.MigrationMana
Data: &migrations.MigrationData{
PathToFile: pathTofile,
CliVersion: CliVersion,
ProjectCliVersion: config.projectSettings.CLI.Version,
ProjectCliVersion: config.projectSettings.Sveltin.Version,
},
}
}
Expand All @@ -130,7 +139,22 @@ func newUpdateThemeConfigMigration(migrationManager *migrations.MigrationManager
Data: &migrations.MigrationData{
PathToFile: pathTofile,
CliVersion: CliVersion,
ProjectCliVersion: config.projectSettings.CLI.Version,
ProjectCliVersion: config.projectSettings.Sveltin.Version,
},
}
}

func newDotEnvMigration(migrationManager *migrations.MigrationManager, config appConfig, pathTofile string) *migrations.UpdateDotEnvMigration {
return &migrations.UpdateDotEnvMigration{
Mediator: migrationManager,
Fs: config.fs,
FsManager: config.fsManager,
PathMaker: config.pathMaker,
Logger: config.log,
Data: &migrations.MigrationData{
PathToFile: pathTofile,
CliVersion: CliVersion,
ProjectCliVersion: config.projectSettings.Sveltin.Version,
},
}
}
23 changes: 0 additions & 23 deletions config/project.go

This file was deleted.

6 changes: 3 additions & 3 deletions internal/fsm/sveltin_fsm.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,21 +89,21 @@ func (s *SveltinFSManager) NewPublicPageFile(pageData *tpltypes.PageData, projec
}

// NewNoPageFile returns a pointer to a 'no-public page' File.
func (s *SveltinFSManager) NewNoPageFile(name string, prodData *tpltypes.EnvProductionData, resources []string, contents map[string][]string) *composer.File {
func (s *SveltinFSManager) NewNoPageFile(name string, data *tpltypes.ProjectSettings, resources []string, contents map[string][]string) *composer.File {
return &composer.File{
Name: name + ".xml",
TemplateID: name,
TemplateData: &config.TemplateData{
NoPage: &tpltypes.NoPageData{
Data: prodData,
Data: data,
Items: helpers.NewNoPageItems(resources, contents),
},
},
}
}

// NewMenuFile returns a pointer to a 'no-public page' File.
func (s *SveltinFSManager) NewMenuFile(name string, prodData *tpltypes.EnvProductionData, resources []string, contents map[string][]string, withContentFlag bool) *composer.File {
func (s *SveltinFSManager) NewMenuFile(name string, resources []string, contents map[string][]string, withContentFlag bool) *composer.File {
return &composer.File{
Name: name + ".js.ts",
TemplateID: name,
Expand Down
10 changes: 6 additions & 4 deletions internal/migrations/defaults-config-migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import (
"github.com/sveltinio/yinlog"
)

// SemVersionRegExp is the regexp pattern for semantic versioning - https://ihateregex.io/expr/semver/
const SemVersionRegExp = `(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?`
// SemVersionPattern is the regexp pattern to identify semantic versioning string - https://ihateregex.io/expr/semver/ .
const SemVersionPattern = `(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?`

//=============================================================================

// UpdateDefaultsConfigMigration is the struct representing the migration update the defaults.js.ts file.
type UpdateDefaultsConfigMigration struct {
Expand Down Expand Up @@ -61,7 +63,7 @@ func (m *UpdateDefaultsConfigMigration) up() error {
}

if exists {
if fileContent, ok := isMigrationRequired(m, SemVersionRegExp, testAsOne); ok {
if fileContent, ok := isMigrationRequired(m, SemVersionPattern, findStringMatcher); ok {
m.Logger.Info(fmt.Sprintf("Migrating %s file", filepath.Base(m.Data.PathToFile)))
if err := updateConfigFile(m, fileContent); err != nil {
return err
Expand Down Expand Up @@ -115,7 +117,7 @@ func updateConfigFile(m *UpdateDefaultsConfigMigration, content []byte) error {
func newSveltinVersionRule(line string) *MigrationRule {
return &MigrationRule{
Value: line,
Pattern: SemVersionRegExp,
Pattern: SemVersionPattern,
IsReplaceFullLine: true,
GetMatchReplacer: func(string) string {
return `import { sveltin } from '../sveltin.json';
Expand Down
139 changes: 139 additions & 0 deletions internal/migrations/dotenv-migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
/**
* Copyright © 2021-present Sveltin contributors <github@sveltin.io>
*
* Use of this source code is governed by Apache 2.0 license
* that can be found in the LICENSE file.
*/

package migrations

import (
"fmt"
"path/filepath"
"regexp"
"strings"

"github.com/spf13/afero"
"github.com/sveltinio/sveltin/common"
"github.com/sveltinio/sveltin/internal/fsm"
"github.com/sveltinio/sveltin/internal/pathmaker"
"github.com/sveltinio/yinlog"
)

// Patterns used by MigrationRule
const (
SitemapPattern = `^sitemap`
)

//=============================================================================

// UpdateDotEnvMigration is the struct representing the migration update the defaults.js.ts file.
type UpdateDotEnvMigration struct {
Mediator MigrationMediator
Fs afero.Fs
FsManager *fsm.SveltinFSManager
PathMaker *pathmaker.SveltinPathMaker
Logger *yinlog.Logger
Data *MigrationData
}

func (m *UpdateDotEnvMigration) getFs() afero.Fs { return m.Fs }
func (m *UpdateDotEnvMigration) getPathMaker() *pathmaker.SveltinPathMaker {
return m.PathMaker
}
func (m *UpdateDotEnvMigration) getLogger() *yinlog.Logger { return m.Logger }
func (m *UpdateDotEnvMigration) getData() *MigrationData { return m.Data }

// Execute return error if migration execution over up and down methods fails.
func (m UpdateDotEnvMigration) Execute() error {
if err := m.up(); err != nil {
return err
}
if err := m.down(); err != nil {
return err
}
return nil
}

func (m *UpdateDotEnvMigration) up() error {

if !m.Mediator.canRun(m) {
return nil
}

exists, err := common.FileExists(m.Fs, m.Data.PathToFile)
if err != nil {
return err
}

if exists {
if fileContent, ok := isMigrationRequired(m, SitemapPattern, findStringMatcher); ok {
m.Logger.Info(fmt.Sprintf("Migrating %s file", filepath.Base(m.Data.PathToFile)))
if err := updateDotEnvFile(m, fileContent); err != nil {
return err
}
}
}

return nil
}

func (m *UpdateDotEnvMigration) down() error {
if err := m.Mediator.notifyAboutCompletion(); err != nil {
return err
}
return nil
}

func (m *UpdateDotEnvMigration) allowUp() error {
if err := m.up(); err != nil {
return err
}
return nil
}

//=============================================================================

func updateDotEnvFile(m *UpdateDotEnvMigration, content []byte) error {
lines := strings.Split(string(content), "\n")
for i, line := range lines {
rules := []*MigrationRule{newDotEnvSitemapRule(line)}
if res, ok := applyMigrationRules(rules); ok {
lines[i] = res
} else {
lines[i] = line
}
}
output := strings.Join(lines, "\n")
err := m.Fs.Remove(m.Data.PathToFile)
if err != nil {
return err
}

cleanedOutput := removeMultiEmptyLines(output)
if err = afero.WriteFile(m.Fs, m.Data.PathToFile, cleanedOutput, 0644); err != nil {
return err
}
return nil
}

//=============================================================================

func newDotEnvSitemapRule(line string) *MigrationRule {
return &MigrationRule{
Value: line,
Pattern: SitemapPattern,
IsReplaceFullLine: true,
GetMatchReplacer: func(string) string {
return ""
},
}
}

// =============================================================================

func removeMultiEmptyLines(content string) []byte {
rule := regexp.MustCompile(`[\n]+`)
output := rule.ReplaceAllString(strings.TrimSpace(content), "\n")
return []byte(output)
}
13 changes: 13 additions & 0 deletions internal/migrations/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ type MigrationRule struct {

type matcherFunc = func([]byte, string, string) ([]byte, bool)

//=============================================================================

func isMigrationRequired(m Migration, pattern string, matcher matcherFunc) ([]byte, bool) {
content, err := afero.ReadFile(m.getFs(), m.getData().PathToFile)
if err != nil {
Expand Down Expand Up @@ -72,3 +74,14 @@ func applyMigrationRules(rules []*MigrationRule) (string, bool) {
}
return "", false
}

//=============================================================================

func findStringMatcher(content []byte, pattern, line string) ([]byte, bool) {
rule := regexp.MustCompile(pattern)
matches := rule.FindString(line)
if len(matches) > 0 {
return content, true
}
return nil, false
}
Loading