@teispace/next-maker 1.18.0 → 1.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/index.js +27 -9
- package/dist/index.js.map +3 -3
- package/dist/src/generators/templates/hook.template.d.ts.map +1 -1
- package/dist/src/generators/templates/persist.template.d.ts.map +1 -1
- package/dist/src/services/setup/i18n/injectors.d.ts.map +1 -1
- package/dist/src/services/setup/validate-scripts/scripts.d.ts +1 -1
- package/dist/src/services/setup/validate-scripts/scripts.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.19.1](https://github.com/teispace/npm-packages/compare/next-maker-v1.19.0...next-maker-v1.19.1) (2026-04-29)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Code Refactoring
|
|
7
|
+
|
|
8
|
+
* remove console logs from loading and error state handlers in hook template ([6cd953a](https://github.com/teispace/npm-packages/commit/6cd953a3f9b82dc37d249644913bbf6110c878b3))
|
|
9
|
+
|
|
10
|
+
## [1.19.0](https://github.com/teispace/npm-packages/compare/next-maker-v1.18.0...next-maker-v1.19.0) (2026-04-28)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
### Features
|
|
14
|
+
|
|
15
|
+
* enhance persist template with migrations and versioning; update HTML lang direction in injectors; add check-only option in env sync script ([e49240c](https://github.com/teispace/npm-packages/commit/e49240c97064a10f3f43bee518b9a02da2879545))
|
|
16
|
+
|
|
3
17
|
## [1.18.0](https://github.com/teispace/npm-packages/compare/next-maker-v1.17.1...next-maker-v1.18.0) (2026-04-26)
|
|
4
18
|
|
|
5
19
|
|
package/dist/index.js
CHANGED
|
@@ -330,14 +330,25 @@ export { ${n} } from './hooks/${n}';
|
|
|
330
330
|
export * from './types/${r}.types';${o?`
|
|
331
331
|
export * from './store';`:""}${i?`
|
|
332
332
|
export * from './services/${r}.service';`:""}
|
|
333
|
-
`};var dn=e=>{let{componentName:r,camelName:t,typesImportPath:n}=e
|
|
334
|
-
import storage from '
|
|
333
|
+
`};var dn=e=>{let{componentName:r,camelName:t,typesImportPath:n}=e,o=`${t.toUpperCase()}_PERSIST_VERSION`;return`import { createMigrate, type PersistConfig, type PersistedState } from 'redux-persist';
|
|
334
|
+
import storage from '@/store/storage';
|
|
335
335
|
import type { ${r}State } from '${n}';
|
|
336
336
|
|
|
337
|
+
const ${o} = 1;
|
|
338
|
+
|
|
339
|
+
const migrations = {
|
|
340
|
+
// Bump ${o} and add a migration here when ${r}State's
|
|
341
|
+
// shape changes. Receives the previously-persisted state, returns the new
|
|
342
|
+
// shape. Returning \`undefined\` discards stale state.
|
|
343
|
+
// 2: (state) => ({ ...state, newField: defaultValue }),
|
|
344
|
+
} satisfies Record<number, (state: PersistedState) => PersistedState>;
|
|
345
|
+
|
|
337
346
|
export const ${t}PersistConfig: PersistConfig<${r}State> = {
|
|
338
347
|
key: '${t}',
|
|
339
348
|
storage,
|
|
349
|
+
version: ${o},
|
|
340
350
|
// whitelist: ['someField'], // Specify which fields to persist
|
|
351
|
+
migrate: createMigrate(migrations, { debug: false }),
|
|
341
352
|
};
|
|
342
353
|
`};var un=e=>{let{componentName:r,camelName:t,sliceName:n}=e;return`import { RootState } from '@/store/rootReducer';
|
|
343
354
|
|
|
@@ -403,12 +414,10 @@ export const ${r} = () => {
|
|
|
403
414
|
|
|
404
415
|
const handleSetLoading = (loading: boolean) => {
|
|
405
416
|
dispatch(setLoading(loading));
|
|
406
|
-
console.log('Loading state updated:', loading);
|
|
407
417
|
};
|
|
408
418
|
|
|
409
419
|
const handleSetError = (error: string | null) => {
|
|
410
420
|
dispatch(setError(error));
|
|
411
|
-
console.log('Error state updated:', error);
|
|
412
421
|
};
|
|
413
422
|
|
|
414
423
|
return {
|
|
@@ -744,6 +753,7 @@ ${h}`}),t=t.replace(/export const RootProvider = \(\{([\s\S]*?)\}:\s*RootProvide
|
|
|
744
753
|
import { hasLocale } from 'next-intl';
|
|
745
754
|
import { notFound } from 'next/navigation';
|
|
746
755
|
import { getMessages, getTimeZone, setRequestLocale } from 'next-intl/server';
|
|
756
|
+
import { getLocaleDirection } from '@/lib/config/app-locales';
|
|
747
757
|
${i}`),!i.includes("generateStaticParams")){let p=i.indexOf("};",i.indexOf("export const metadata"));if(p!==-1){let d=p+2;i=i.slice(0,d)+`
|
|
748
758
|
|
|
749
759
|
export function generateStaticParams() {
|
|
@@ -761,7 +771,7 @@ export function generateStaticParams() {
|
|
|
761
771
|
setRequestLocale(locale);
|
|
762
772
|
|
|
763
773
|
const [messages, timeZone] = await Promise.all([getMessages(), getTimeZone()]);
|
|
764
|
-
`+i.slice(h+1)}i=i.replace(/<RootProvider>/,"<RootProvider locale={locale} messages={messages} timeZone={timeZone}>"),i=i.replace(/<html lang="en"/,"<html lang={locale}")}await f(o,i),await T(r)}if(m(t)){let o=re.join(n,"page.tsx"),i=await u(t);i.includes("next-intl")||(i=`import { SupportedLocale } from '@/types/i18n';
|
|
774
|
+
`+i.slice(h+1)}i=i.replace(/<RootProvider>/,"<RootProvider locale={locale} messages={messages} timeZone={timeZone}>"),i=i.replace(/<html lang="en"/,"<html lang={locale} dir={getLocaleDirection(locale)}")}await f(o,i),await T(r)}if(m(t)){let o=re.join(n,"page.tsx"),i=await u(t);i.includes("next-intl")||(i=`import { SupportedLocale } from '@/types/i18n';
|
|
765
775
|
import { setRequestLocale } from 'next-intl/server';
|
|
766
776
|
${i}`),i=i.replace(/export default function Home\(\)/,`type Props = {
|
|
767
777
|
params: Promise<{ locale: string }>;
|
|
@@ -799,6 +809,8 @@ ${e.map(({key:t,value:n})=>` { key: '${t}', value: '${n}' },`).join(`
|
|
|
799
809
|
},`,we=e=>Ta.test(e),or=(e,r=Ro)=>{if(we(e))return e;if(!Eo.test(e))throw new Error("Could not locate `const nextConfig: NextConfig = {` in next.config.ts.");return e.replace(Eo,`$1${Ea(r)}`)};var Be=async e=>{let r=R("Adding security headers to next.config.ts...");try{let t=Ra.join(e,c.NEXT_CONFIG);if(!m(t))throw new Error(`${c.NEXT_CONFIG} not found.`);let n=await u(t);if(we(n)){r.succeed("Security headers already configured.");return}let o=or(n);await f(t,o),r.succeed($a.green("Security headers added."))}catch(t){throw r.fail("Failed to add security headers."),t}};var $o={id:"security-headers",name:"Security Headers",description:"Hardened HTTP headers in next.config.ts",detect:async e=>{let r=ba.join(e,c.NEXT_CONFIG);return m(r)?we(await u(r)):!1},files:[],packages:[],scripts:[],injections:[{file:c.NEXT_CONFIG,description:"headers() function in next.config.ts",presence:/^\s+headers\s*:/m,removePattern:/\s+headers:\s*async\s*\(\)\s*=>\s*\{[\s\S]*?\n\s{0,2}\},/m}],apply:Be};w();P();import Oa from"node:path";w();import Na from"node:fs/promises";import ae from"node:path";import Ia from"degit";import Aa from"picocolors";P();var ka=["vitest","jsdom","@vitejs/plugin-react","@testing-library/dom","@testing-library/jest-dom","@testing-library/react","@testing-library/user-event"],Xe=async e=>{let r=R("Setting up testing (Vitest + RTL)..."),t=ae.join(e,".next-maker-temp-tests");try{let n=ae.join(e,c.VITEST_CONFIG);if(m(n)){r.fail("Testing is already set up (vitest.config.ts exists).");return}r.text="Fetching assets from starter repo...",await Ia("teispace/nextjs-starter",{cache:!1,force:!0,verbose:!1}).clone(t),await _(ae.join(t,c.VITEST_CONFIG),ae.join(e,c.VITEST_CONFIG));let i=ae.join(e,c.TEST_DIR);await Na.mkdir(i,{recursive:!0}),await _(ae.join(t,c.TEST_DIR,"setup.ts"),ae.join(i,"setup.ts"));let s=ae.join(e,c.PACKAGE_JSON),a=JSON.parse(await u(s)),p={...a.dependencies,...a.devDependencies},d=!!(p["@reduxjs/toolkit"]&&p["react-redux"]),g=!!p["next-intl"];await ne(e,{redux:d,i18n:g}),await k(s,x=>(x.scripts=x.scripts??{},x.scripts.test=x.scripts.test??"vitest run",x.scripts["test:watch"]=x.scripts["test:watch"]??"vitest",x.scripts["test:coverage"]=x.scripts["test:coverage"]??"vitest run --coverage",typeof x.scripts.validate=="string"&&!/\byarn\s+test(?![:\w])/.test(x.scripts.validate)&&(x.scripts.validate=x.scripts.validate.replace(/(\byarn\s+check:deprecated\s*)(&&)/,"$1&& yarn test $2")),x)),r.text="Installing testing devDependencies...";let h=await O(e);await ue(e,h,ka),r.text="Formatting code...",await U(e,h,"lint:fix"),r.succeed(Aa.green("Testing setup complete."))}catch(n){throw r.fail("Failed to set up testing."),n}finally{await S(t)}};var bo={id:"tests",name:"Tests",description:"Vitest + React Testing Library + jsdom",detect:async e=>m(Oa.join(e,c.VITEST_CONFIG)),files:[{path:c.VITEST_CONFIG,generated:!0},{path:"test",generated:!0,isDir:!0,containsUserContent:!0,removeHint:"holds setup.ts / test-utils.tsx and any helpers you added \u2014 review before deleting"}],packages:[{name:"vitest",kind:"devDependency"},{name:"jsdom",kind:"devDependency"},{name:"@vitejs/plugin-react",kind:"devDependency"},{name:"@testing-library/dom",kind:"devDependency"},{name:"@testing-library/jest-dom",kind:"devDependency"},{name:"@testing-library/react",kind:"devDependency"},{name:"@testing-library/user-event",kind:"devDependency"}],scripts:[{name:"test",expectedValue:"vitest run"},{name:"test:watch",expectedValue:"vitest"}],injections:[],apply:Xe};P();import La from"node:path";w();import No from"node:path";import ja from"picocolors";P();var _a={npm:"npm run",yarn:"yarn",pnpm:"pnpm",bun:"bun run"},Fa=e=>{let r=_a[e];return["ci:check","type-check","check:deprecated","test","build"].map(t=>`${r} ${t}`).join(" && ")},ir=(e,r)=>{let t={...e.scripts??{}},n={...e.devDependencies??{}};return t["env:sync"]||(t["env:sync"]="tsx scripts/sync-env.ts"),t["check:deprecated"]||(t["check:deprecated"]="tsx scripts/check-deprecated.ts"),t["type-check"]||(t["type-check"]="tsc --noEmit"),t.validate||(t.validate=Fa(r)),!n.tsx&&!e.dependencies?.hasOwnProperty("tsx")&&(n.tsx="*"),{...e,scripts:t,devDependencies:n}};var sr=`import * as fs from 'node:fs';
|
|
800
810
|
import * as path from 'node:path';
|
|
801
811
|
|
|
812
|
+
const checkOnly = process.argv.includes('--check');
|
|
813
|
+
|
|
802
814
|
const envPath = path.join(process.cwd(), '.env');
|
|
803
815
|
const examplePath = path.join(process.cwd(), '.env.example');
|
|
804
816
|
|
|
@@ -856,12 +868,18 @@ if (fs.existsSync(examplePath)) {
|
|
|
856
868
|
currentExampleContent = fs.readFileSync(examplePath, 'utf-8');
|
|
857
869
|
}
|
|
858
870
|
|
|
859
|
-
if (currentExampleContent
|
|
860
|
-
fs.writeFileSync(examplePath, newExampleContent);
|
|
861
|
-
console.log('\u2705 Synchronized .env.example with .env');
|
|
862
|
-
} else {
|
|
871
|
+
if (currentExampleContent === newExampleContent) {
|
|
863
872
|
console.log('\u2728 .env.example is already up to date');
|
|
873
|
+
process.exit(0);
|
|
864
874
|
}
|
|
875
|
+
|
|
876
|
+
if (checkOnly) {
|
|
877
|
+
console.error('\u274C .env.example is out of sync with .env. Run "yarn env:sync" to update.');
|
|
878
|
+
process.exit(1);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
fs.writeFileSync(examplePath, newExampleContent);
|
|
882
|
+
console.log('\u2705 Synchronized .env.example with .env');
|
|
865
883
|
`,ar=`/**
|
|
866
884
|
* Walks every identifier in the project and flags any whose resolved TypeScript
|
|
867
885
|
* symbol carries a \`@deprecated\` JSDoc tag. Catches deprecated API usage that
|