@quilted/create 0.1.13 → 0.1.16

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.
Files changed (73) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/build/cjs/_commonjsHelpers.cjs +10 -0
  3. package/build/cjs/app.cjs +303 -0
  4. package/build/cjs/index.cjs +5220 -5198
  5. package/build/cjs/index2.cjs +374 -0
  6. package/build/cjs/index3.cjs +7854 -0
  7. package/build/cjs/minimatch.cjs +1202 -0
  8. package/build/cjs/package-manager.cjs +305 -0
  9. package/build/cjs/package.cjs +410 -0
  10. package/build/cjs/parser-babel.cjs +59 -0
  11. package/build/cjs/parser-yaml.cjs +182 -0
  12. package/build/cjs/standalone.cjs +147 -0
  13. package/build/esm/_commonjsHelpers.mjs +7 -0
  14. package/build/esm/app.mjs +280 -0
  15. package/build/esm/index.mjs +5206 -5195
  16. package/build/esm/index2.mjs +365 -0
  17. package/build/esm/index3.mjs +7852 -0
  18. package/build/esm/minimatch.mjs +1200 -0
  19. package/build/esm/package-manager.mjs +275 -0
  20. package/build/esm/package.mjs +387 -0
  21. package/build/esm/parser-babel.mjs +57 -0
  22. package/build/esm/parser-yaml.mjs +180 -0
  23. package/build/esm/standalone.mjs +145 -0
  24. package/build/tsconfig.tsbuildinfo +1 -1
  25. package/build/typescript/app.d.ts +2 -0
  26. package/build/typescript/app.d.ts.map +1 -0
  27. package/build/typescript/help.d.ts +6 -0
  28. package/build/typescript/help.d.ts.map +1 -0
  29. package/build/typescript/package.d.ts +2 -0
  30. package/build/typescript/package.d.ts.map +1 -0
  31. package/build/typescript/shared/package-manager.d.ts +3 -0
  32. package/build/typescript/shared/package-manager.d.ts.map +1 -0
  33. package/build/typescript/shared/prompts.d.ts +22 -0
  34. package/build/typescript/shared/prompts.d.ts.map +1 -0
  35. package/build/typescript/shared/tsconfig.d.ts +3 -0
  36. package/build/typescript/shared/tsconfig.d.ts.map +1 -0
  37. package/build/typescript/shared.d.ts +21 -0
  38. package/build/typescript/shared.d.ts.map +1 -0
  39. package/package.json +13 -3
  40. package/source/app.ts +387 -0
  41. package/source/create.ts +43 -383
  42. package/source/help.ts +132 -0
  43. package/source/package.ts +510 -0
  44. package/source/shared/package-manager.ts +74 -0
  45. package/source/shared/prompts.ts +133 -0
  46. package/source/shared/tsconfig.ts +90 -0
  47. package/source/shared.ts +170 -0
  48. package/templates/{app → app-basic}/App.tsx +4 -7
  49. package/templates/{app → app-basic}/features/Start/Start.module.css +0 -0
  50. package/templates/{app → app-basic}/features/Start/Start.tsx +1 -1
  51. package/templates/{app → app-basic}/features/Start/index.ts +0 -0
  52. package/templates/{app → app-basic}/foundation/Head.tsx +8 -8
  53. package/templates/{app → app-basic}/foundation/Http.tsx +10 -6
  54. package/templates/{app → app-basic}/package.json +10 -1
  55. package/templates/{app → app-basic}/quilt.project.ts +0 -0
  56. package/templates/{app → app-basic}/server.tsx +0 -0
  57. package/templates/{app → app-basic}/shared/types.ts +0 -0
  58. package/templates/{app → app-basic}/tsconfig.json +0 -0
  59. package/templates/app-single-file/App.tsx +168 -0
  60. package/templates/app-single-file/package.json +30 -0
  61. package/templates/app-single-file/quilt.project.ts +6 -0
  62. package/templates/app-single-file/tsconfig.json +9 -0
  63. package/templates/{workspace → github}/_github/workflows/actions/prepare/action.yml +0 -0
  64. package/templates/{workspace → github}/_github/workflows/ci.yml +0 -0
  65. package/templates/package/package.json +24 -9
  66. package/templates/package/quilt.project.ts +1 -1
  67. package/templates/vscode/_vscode/extensions.json +7 -0
  68. package/templates/vscode/_vscode/settings.json +17 -0
  69. package/templates/workspace/_gitignore +1 -1
  70. package/templates/workspace/_prettierignore +1 -0
  71. package/templates/workspace/package.json +1 -7
  72. package/templates/workspace/tsconfig.json +6 -1
  73. package/templates/workspace/pnpm-workspace.yaml +0 -3
@@ -0,0 +1,90 @@
1
+ import {relative} from 'path';
2
+
3
+ import type {OutputTarget} from '../shared';
4
+ import {format, relativeDirectoryForDisplay} from '../shared';
5
+
6
+ interface TSConfigReference {
7
+ path: string;
8
+ }
9
+
10
+ const ENDS_WITH_TSCONFIG = /[/]?tsconfig[.a-z0-9]*[.]json/i;
11
+
12
+ export async function addToTsConfig(directory: string, output: OutputTarget) {
13
+ const tsconfig = JSON.parse(await output.read('tsconfig.json'));
14
+
15
+ tsconfig.references ??= [];
16
+
17
+ const relativePath = relative(output.root, directory);
18
+ const relativeForDisplay = relativeDirectoryForDisplay(relativePath);
19
+
20
+ if (tsconfig.references.length === 0) {
21
+ tsconfig.references.push({path: relativeForDisplay});
22
+ } else {
23
+ let hasExistingReference = false;
24
+ let referenceFormat:
25
+ | 'relative'
26
+ | 'pretty-relative'
27
+ | 'tsconfig'
28
+ | 'pretty-tsconfig' = 'pretty-relative';
29
+
30
+ for (const {path} of tsconfig.references as TSConfigReference[]) {
31
+ if (path.startsWith('./')) {
32
+ if (ENDS_WITH_TSCONFIG.test(path)) {
33
+ referenceFormat = 'pretty-tsconfig';
34
+
35
+ if (path === `${relativeForDisplay}/tsconfig.json`) {
36
+ hasExistingReference = true;
37
+ break;
38
+ }
39
+ }
40
+
41
+ referenceFormat = 'pretty-relative';
42
+
43
+ if (path === relativeForDisplay) {
44
+ hasExistingReference = true;
45
+ break;
46
+ }
47
+ } else if (ENDS_WITH_TSCONFIG.test(path)) {
48
+ referenceFormat = 'tsconfig';
49
+
50
+ if (path === `${relativePath}/tsconfig.json`) {
51
+ hasExistingReference = true;
52
+ break;
53
+ }
54
+ } else {
55
+ referenceFormat = 'relative';
56
+
57
+ if (path === relativePath) {
58
+ hasExistingReference = true;
59
+ break;
60
+ }
61
+ }
62
+ }
63
+
64
+ if (!hasExistingReference) {
65
+ let path: string;
66
+
67
+ if (referenceFormat === 'pretty-tsconfig') {
68
+ path = `${relativeForDisplay}/tsconfig.json`;
69
+ } else if (referenceFormat === 'pretty-relative') {
70
+ path = relativeForDisplay;
71
+ } else if (referenceFormat === 'tsconfig') {
72
+ path = `${relativePath}/tsconfig.json`;
73
+ } else {
74
+ path = relativePath;
75
+ }
76
+
77
+ tsconfig.references.push({path});
78
+ }
79
+ }
80
+
81
+ tsconfig.references = tsconfig.references.sort(
82
+ ({path: pathOne}: TSConfigReference, {path: pathTwo}: TSConfigReference) =>
83
+ pathOne.localeCompare(pathTwo),
84
+ );
85
+
86
+ await output.write(
87
+ 'tsconfig.json',
88
+ await format(JSON.stringify(tsconfig), {as: 'json'}),
89
+ );
90
+ }
@@ -0,0 +1,170 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ import {fileURLToPath} from 'url';
4
+ import type {BuiltInParserName} from 'prettier';
5
+
6
+ export {prompt} from './shared/prompts';
7
+
8
+ export function loadTemplate(
9
+ name:
10
+ | 'package'
11
+ | 'app-basic'
12
+ | 'app-single-file'
13
+ | 'workspace'
14
+ | 'github'
15
+ | 'vscode',
16
+ ) {
17
+ let templateRootPromise: Promise<string> | undefined;
18
+
19
+ return {
20
+ async copy(to: string, handleFile?: (file: string) => boolean) {
21
+ templateRootPromise ??= templateDirectory(name);
22
+ const templateRoot = await templateRootPromise;
23
+ const targetRoot = path.resolve(to);
24
+
25
+ const files = fs
26
+ .readdirSync(templateRoot)
27
+ .filter((file) => !path.basename(file).startsWith('.'));
28
+
29
+ for (const file of files) {
30
+ if (handleFile) {
31
+ if (!handleFile(file)) {
32
+ continue;
33
+ }
34
+ }
35
+
36
+ const targetPath = path.join(
37
+ targetRoot,
38
+ file.startsWith('_') ? `.${file.slice(1)}` : file,
39
+ );
40
+
41
+ copy(path.join(templateRoot, file), targetPath);
42
+ }
43
+ },
44
+ async read(file: string) {
45
+ templateRootPromise ??= templateDirectory(name);
46
+ const templateRoot = await templateRootPromise;
47
+
48
+ return fs.readFileSync(path.join(templateRoot, file), {encoding: 'utf8'});
49
+ },
50
+ };
51
+ }
52
+
53
+ export interface OutputTarget {
54
+ readonly root: string;
55
+ read(file: string): Promise<string>;
56
+ write(file: string, content: string): Promise<void>;
57
+ }
58
+
59
+ export function createOutputTarget(target: string): OutputTarget {
60
+ return {
61
+ root: target,
62
+ read(file: string) {
63
+ return fs.promises.readFile(path.resolve(target, file), {
64
+ encoding: 'utf8',
65
+ });
66
+ },
67
+ async write(file: string, content: string) {
68
+ await writeFile(path.resolve(target, file), content);
69
+ },
70
+ };
71
+ }
72
+
73
+ let packageRootPromise: Promise<string> | undefined;
74
+
75
+ async function templateDirectory(
76
+ name:
77
+ | 'package'
78
+ | 'app-basic'
79
+ | 'app-single-file'
80
+ | 'workspace'
81
+ | 'github'
82
+ | 'vscode',
83
+ ) {
84
+ return path.join(await getPackageRoot(), 'templates', name);
85
+ }
86
+
87
+ async function getPackageRoot(): Promise<string> {
88
+ if (!packageRootPromise) {
89
+ packageRootPromise = (async () => {
90
+ const {packageDirectory} = await import('pkg-dir');
91
+
92
+ return packageDirectory({
93
+ cwd: path.dirname(fileURLToPath(import.meta.url)),
94
+ });
95
+ })();
96
+ }
97
+
98
+ return packageRootPromise;
99
+ }
100
+
101
+ export function toValidPackageName(projectName: string) {
102
+ return projectName
103
+ .trim()
104
+ .toLowerCase()
105
+ .replace(/\s+/g, '-')
106
+ .replace(/^[._]/, '')
107
+ .replace(/[^a-z0-9-~@/]+/g, '-');
108
+ }
109
+
110
+ function copy(source: string, destination: string) {
111
+ const stat = fs.statSync(source);
112
+ if (stat.isDirectory()) {
113
+ copyDirectory(source, destination);
114
+ } else {
115
+ fs.copyFileSync(source, destination);
116
+ }
117
+ }
118
+
119
+ async function copyDirectory(source: string, destination: string) {
120
+ fs.mkdirSync(destination, {recursive: true});
121
+ for (const file of fs.readdirSync(source)) {
122
+ const srcFile = path.resolve(source, file);
123
+ const destFile = path.resolve(destination, file);
124
+ copy(srcFile, destFile);
125
+ }
126
+ }
127
+
128
+ export async function writeFile(file: string, content: string) {
129
+ await fs.promises.writeFile(file, content);
130
+ }
131
+
132
+ export async function isEmpty(path: string) {
133
+ return fs.readdirSync(path).length === 0;
134
+ }
135
+
136
+ export async function emptyDirectory(dir: string) {
137
+ if (!fs.existsSync(dir)) {
138
+ return;
139
+ }
140
+
141
+ for (const file of fs.readdirSync(dir)) {
142
+ fs.rmSync(path.resolve(dir, file), {force: true, recursive: true});
143
+ }
144
+ }
145
+
146
+ export function relativeDirectoryForDisplay(relativeDirectory: string) {
147
+ return relativeDirectory.startsWith('.')
148
+ ? relativeDirectory
149
+ : `.${path.sep}${relativeDirectory}`;
150
+ }
151
+
152
+ export async function format(
153
+ content: string,
154
+ {as: parser}: {as: BuiltInParserName},
155
+ ) {
156
+ const [{format}, {default: babel}, {default: yaml}] = await Promise.all([
157
+ import('prettier/standalone'),
158
+ import('prettier/parser-babel'),
159
+ import('prettier/parser-yaml'),
160
+ ]);
161
+
162
+ return format(content, {
163
+ arrowParens: 'always',
164
+ bracketSpacing: false,
165
+ singleQuote: true,
166
+ trailingComma: 'all',
167
+ parser,
168
+ plugins: [babel, yaml],
169
+ });
170
+ }
@@ -5,9 +5,8 @@ import {Head} from './foundation/Head';
5
5
 
6
6
  import {Start} from './features/Start';
7
7
 
8
- /**
9
- * The root component for your application.
10
- */
8
+ // The root component for your application. You will typically render any
9
+ // app-wide context in this component.
11
10
  export default function App() {
12
11
  return (
13
12
  <AppContext>
@@ -20,10 +19,8 @@ export default function App() {
20
19
  );
21
20
  }
22
21
 
23
- /**
24
- * This component renders the routes for your application. If you have a lot
25
- * of routes, you may want to split this component into its own file.
26
- */
22
+ // This component renders the routes for your application. If you have a lot
23
+ // of routes, you may want to split this component into its own file.
27
24
  function Routes() {
28
25
  return useRoutes([{match: '/', render: () => <Start />}]);
29
26
  }
@@ -1,5 +1,5 @@
1
1
  import styles from './Start.module.css';
2
2
 
3
3
  export function Start() {
4
- return <div className={styles.Start}>Hello world!!!</div>;
4
+ return <div className={styles.Start}>Hello world!</div>;
5
5
  }
@@ -1,26 +1,26 @@
1
1
  import {Title, Viewport, Favicon, SearchRobots} from '@quilted/quilt/html';
2
2
 
3
+ // This component sets details of the HTML page. If you need to customize
4
+ // any of these details based on conditions like the active route, or some
5
+ // state about the user, you can move these components to wherever in your
6
+ // application you can read that state.
3
7
  export function Head() {
4
8
  return (
5
9
  <>
6
- {/**
7
- * Sets the default `<title>` for this application.
8
- */}
10
+ {/* Sets the default `<title>` for this application. */}
9
11
  <Title>App</Title>
10
12
 
11
- {/**
13
+ {/*
12
14
  * Sets the default favicon used by the application. You can
13
15
  * change this to a different emoji, make it `blank`, or pass
14
16
  * a URL with the `source` prop.
15
17
  */}
16
18
  <Favicon emoji="🧶" />
17
19
 
18
- {/**
19
- * Adds a responsive-friendly `viewport` `<meta>` tag.
20
- */}
20
+ {/* Adds a responsive-friendly `viewport` `<meta>` tag. */}
21
21
  <Viewport cover />
22
22
 
23
- {/**
23
+ {/*
24
24
  * Disables all search indexing for this application. If you are
25
25
  * building an unauthenticated app, you probably want to remove
26
26
  * this component, or update it to control how your site is indexed
@@ -8,12 +8,16 @@ import {
8
8
  StrictTransportSecurity,
9
9
  } from '@quilted/quilt/http';
10
10
 
11
+ // This component sets details on the HTTP response for all HTML server-rendering
12
+ // requests. If you need to customize any of these details based on conditions like
13
+ // the active route, or some state about the user, you can move these components to
14
+ // wherever in your application you can read that state.
11
15
  export function Http() {
12
16
  const isHttps = useCurrentUrl().protocol === 'https:';
13
17
 
14
18
  return (
15
19
  <>
16
- {/**
20
+ {/*
17
21
  * Disables the cache for this page, which is generally the best option
18
22
  * when dealing with authenticated content. If your site doesn’t have
19
23
  * authentication, or you have a better cache policy that works for your
@@ -23,7 +27,7 @@ export function Http() {
23
27
  */}
24
28
  <CacheControl cache={false} />
25
29
 
26
- {/**
30
+ {/*
27
31
  * Sets a strict content security policy for this page. If you load
28
32
  * assets from other origins, or want to allow some more dangerous
29
33
  * resource loading techniques like `eval`, you can change the
@@ -50,7 +54,7 @@ export function Http() {
50
54
  upgradeInsecureRequests={isHttps}
51
55
  />
52
56
 
53
- {/**
57
+ {/*
54
58
  * Sets a strict permissions policy for this page, which limits access
55
59
  * to some native browser features.
56
60
  *
@@ -73,7 +77,7 @@ export function Http() {
73
77
  geolocation={false}
74
78
  />
75
79
 
76
- {/**
80
+ {/*
77
81
  * Instructs browsers to only load this page over HTTPS using the
78
82
  * `Strict-Transport-Security` header.
79
83
  *
@@ -81,7 +85,7 @@ export function Http() {
81
85
  */}
82
86
  {isHttps && <StrictTransportSecurity />}
83
87
 
84
- {/**
88
+ {/*
85
89
  * Controls how much information about the current page is included in
86
90
  * requests (through the `Referer` header). The default value
87
91
  * (strict-origin-when-cross-origin) means that only the origin is included
@@ -95,7 +99,7 @@ export function Http() {
95
99
  value="strict-origin-when-cross-origin"
96
100
  />
97
101
 
98
- {/**
102
+ {/*
99
103
  * Instructs browsers to respect the MIME type in the `Content-Type` header.
100
104
  *
101
105
  * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
@@ -1,9 +1,18 @@
1
1
  {
2
- "name": "template-app",
2
+ "name": "template-app-basic",
3
3
  "type": "module",
4
4
  "version": "0.0.0",
5
5
  "private": true,
6
+ "scripts": {
7
+ "start": "node ./build/server/index.js"
8
+ },
6
9
  "dependencies": {},
10
+ "devDependencies": {
11
+ "@quilted/quilt": "^0.5.0",
12
+ "@types/react": "^17.0.0",
13
+ "react": "npm:@quilted/react@^17.0.0",
14
+ "react-dom": "npm:@quilted/react-dom@^17.0.0"
15
+ },
7
16
  "eslintConfig": {
8
17
  "extends": "@quilted/eslint-config/app"
9
18
  },
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,168 @@
1
+ import {Router, useRoutes, useCurrentUrl, AppContext} from '@quilted/quilt';
2
+ import {Title, Viewport, Favicon, SearchRobots} from '@quilted/quilt/html';
3
+ import {
4
+ CacheControl,
5
+ ResponseHeader,
6
+ ContentSecurityPolicy,
7
+ PermissionsPolicy,
8
+ StrictTransportSecurity,
9
+ } from '@quilted/quilt/http';
10
+ import Env from '@quilted/quilt/env';
11
+
12
+ // The root component for your application. You will typically render any
13
+ // app-wide context in this component.
14
+ export default function App() {
15
+ return (
16
+ <AppContext>
17
+ <Router>
18
+ <Http />
19
+ <Head />
20
+ <Routes />
21
+ </Router>
22
+ </AppContext>
23
+ );
24
+ }
25
+
26
+ // This component renders the routes for your application. If you have a lot
27
+ // of routes, you may want to split this component into its own file.
28
+ function Routes() {
29
+ return useRoutes([{match: '/', render: () => <Start />}]);
30
+ }
31
+
32
+ // This component will be rendered for the root URL of your application. Feel
33
+ // free to edit it, rename it, remove it entirely, or move it to a dedicated file.
34
+ function Start() {
35
+ return <div>Hello world!</div>;
36
+ }
37
+
38
+ // This component sets details of the HTML page. If you need to customize
39
+ // any of these details based on conditions like the active route, or some
40
+ // state about the user, you can move these components to wherever in your
41
+ // application you can read that state.
42
+ function Head() {
43
+ return (
44
+ <>
45
+ {/* Sets the default `<title>` for this application. */}
46
+ <Title>App</Title>
47
+
48
+ {/*
49
+ * Sets the default favicon used by the application. You can
50
+ * change this to a different emoji, make it `blank`, or pass
51
+ * a URL with the `source` prop.
52
+ */}
53
+ <Favicon emoji="🧶" />
54
+
55
+ {/* Adds a responsive-friendly `viewport` `<meta>` tag. */}
56
+ <Viewport cover />
57
+
58
+ {/*
59
+ * Disables all search indexing for this application. If you are
60
+ * building an unauthenticated app, you probably want to remove
61
+ * this component, or update it to control how your site is indexed
62
+ * by search engines.
63
+ */}
64
+ <SearchRobots index={false} follow={false} />
65
+ </>
66
+ );
67
+ }
68
+
69
+ // This component sets details on the HTTP response for all HTML server-rendering
70
+ // requests. If you need to customize any of these details based on conditions like
71
+ // the active route, or some state about the user, you can move these components to
72
+ // wherever in your application you can read that state.
73
+ export function Http() {
74
+ const isHttps = useCurrentUrl().protocol === 'https:';
75
+
76
+ return (
77
+ <>
78
+ {/*
79
+ * Disables the cache for this page, which is generally the best option
80
+ * when dealing with authenticated content. If your site doesn’t have
81
+ * authentication, or you have a better cache policy that works for your
82
+ * app or deployment, make sure to update this component accordingly!
83
+ *
84
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control
85
+ */}
86
+ <CacheControl cache={false} />
87
+
88
+ {/*
89
+ * Sets a strict content security policy for this page. If you load
90
+ * assets from other origins, or want to allow some more dangerous
91
+ * resource loading techniques like `eval`, you can change the
92
+ * `defaultSources` to be less restrictive, or add additional items
93
+ * to the allowlist for more specific directives.
94
+ *
95
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy
96
+ */}
97
+ <ContentSecurityPolicy
98
+ reportOnly={Env.MODE === 'development'}
99
+ // By default, only allow sources from the page’s origin.
100
+ defaultSources={["'self'"]}
101
+ // Includes `'unsafe-inline'` because CSS is often necessary in development,
102
+ // and can be difficult to avoid in production.
103
+ styleSources={["'self'", "'unsafe-inline'"]}
104
+ // Includes `data:` so that an inline image can be used for the favicon.
105
+ // If you do not use the `emoji` or `blank` favicons in your app, and you
106
+ // do not load any other images as data URIs, you can remove this directive.
107
+ imageSources={["'self'", 'data:']}
108
+ // Don’t allow this page to be rendered as a frame from a different origin.
109
+ frameAncestors={false}
110
+ // Ensure that all requests made by this page are made over https, unless
111
+ // it is being served over http (typically, during local development)
112
+ upgradeInsecureRequests={isHttps}
113
+ />
114
+
115
+ {/*
116
+ * Sets a strict permissions policy for this page, which limits access
117
+ * to some native browser features.
118
+ *
119
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Feature-Policy
120
+ */}
121
+ <PermissionsPolicy
122
+ // Disables Google’s Federated Learning of Cohorts (“FLoC”) tracking initiative.
123
+ // @see https://www.eff.org/deeplinks/2021/03/googles-floc-terrible-idea
124
+ interestCohort={false}
125
+ // Don’t use synchronous XHRs!
126
+ // @see https://featurepolicy.info/policies/sync-xhr
127
+ syncXhr={false}
128
+ // Disables access to a few device APIs that are infrequently used
129
+ // and prone to abuse. If your application uses these APIs intentionally,
130
+ // feel free to remove the prop, or pass an array containing the origins
131
+ // that should be allowed to use this feature (e.g., `['self']` to allow
132
+ // only the main page’s origin).
133
+ camera={false}
134
+ microphone={false}
135
+ geolocation={false}
136
+ />
137
+
138
+ {/*
139
+ * Instructs browsers to only load this page over HTTPS using the
140
+ * `Strict-Transport-Security` header.
141
+ *
142
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
143
+ */}
144
+ {isHttps && <StrictTransportSecurity />}
145
+
146
+ {/*
147
+ * Controls how much information about the current page is included in
148
+ * requests (through the `Referer` header). The default value
149
+ * (strict-origin-when-cross-origin) means that only the origin is included
150
+ * for cross-origin requests, while the origin, path, and querystring
151
+ * are included for same-origin requests.
152
+ *
153
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy
154
+ */}
155
+ <ResponseHeader
156
+ name="Referrer-Policy"
157
+ value="strict-origin-when-cross-origin"
158
+ />
159
+
160
+ {/*
161
+ * Instructs browsers to respect the MIME type in the `Content-Type` header.
162
+ *
163
+ * @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
164
+ */}
165
+ <ResponseHeader name="X-Content-Type-Options" value="nosniff" />
166
+ </>
167
+ );
168
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "template-app-single-file",
3
+ "type": "module",
4
+ "version": "0.0.0",
5
+ "private": true,
6
+ "scripts": {
7
+ "start": "node ./build/server/index.js"
8
+ },
9
+ "dependencies": {},
10
+ "devDependencies": {
11
+ "@quilted/quilt": "^0.5.0",
12
+ "@types/react": "^17.0.0",
13
+ "react": "npm:@quilted/react@^17.0.0",
14
+ "react-dom": "npm:@quilted/react-dom@^17.0.0"
15
+ },
16
+ "eslintConfig": {
17
+ "extends": "@quilted/eslint-config/app"
18
+ },
19
+ "browserslist": {
20
+ "defaults": [
21
+ "extends @quilted/browserslist-config/defaults"
22
+ ],
23
+ "modules": [
24
+ "extends @quilted/browserslist-config/modules"
25
+ ],
26
+ "evergreen": [
27
+ "extends @quilted/browserslist-config/evergreen"
28
+ ]
29
+ }
30
+ }
@@ -0,0 +1,6 @@
1
+ import {createApp, quiltApp} from '@quilted/craft';
2
+
3
+ export default createApp((app) => {
4
+ app.entry('./App');
5
+ app.use(quiltApp());
6
+ });
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "@quilted/typescript/app.json",
3
+ "compilerOptions": {
4
+ "outDir": "build/typescript"
5
+ },
6
+ "include": ["**/*"],
7
+ "exclude": ["quilt.project.ts", "*.test.ts", "*.test.tsx", "build"],
8
+ "references": []
9
+ }