ras-stack 2.0.2 → 3.0.0
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/README.md +15 -42
- package/dist/changesets/cli.d.ts +1 -0
- package/dist/changesets/cli.js +14 -0
- package/dist/changesets/cli.js.map +1 -0
- package/dist/{policy/changesets.js → changesets/index.js} +1 -1
- package/dist/changesets/index.js.map +1 -0
- package/dist/cli.d.ts +2 -6
- package/dist/cli.js +3 -7
- package/dist/cli.js.map +1 -1
- package/dist/posthog/index.d.ts +0 -2
- package/dist/posthog/index.js +0 -1
- package/dist/posthog/index.js.map +1 -1
- package/package.json +12 -39
- package/config/oxlint/application.json +0 -16
- package/config/oxlint/domain.json +0 -29
- package/config/oxlint/layers.json +0 -116
- package/config/oxlint/tanstack.json +0 -4
- package/config/oxlint.json +0 -19
- package/config/typescript/base.json +0 -10
- package/config/typescript/browser.json +0 -8
- package/config/typescript/bundler.json +0 -9
- package/config/typescript/library.json +0 -11
- package/config/typescript/node-bundler.json +0 -9
- package/config/typescript/tanstack.json +0 -6
- package/dist/create/index.d.ts +0 -1
- package/dist/create/index.js +0 -83
- package/dist/create/index.js.map +0 -1
- package/dist/create/template/.env.example +0 -16
- package/dist/create/template/.oxfmtrc.json +0 -7
- package/dist/create/template/Dockerfile +0 -37
- package/dist/create/template/Dockerfile.standalone +0 -29
- package/dist/create/template/centrifugo.json +0 -14
- package/dist/create/template/dockerignore.template +0 -8
- package/dist/create/template/drizzle/0000_production_reference.sql +0 -114
- package/dist/create/template/drizzle/meta/_journal.json +0 -13
- package/dist/create/template/e2e/full-stack.spec.ts +0 -54
- package/dist/create/template/gitignore.template +0 -9
- package/dist/create/template/oxlint.json +0 -4
- package/dist/create/template/package.json +0 -60
- package/dist/create/template/playwright.config.ts +0 -7
- package/dist/create/template/pnpm-workspace.template.yaml +0 -13
- package/dist/create/template/ras-stack.assets.json +0 -4
- package/dist/create/template/scripts/containerRuntime.ts +0 -29
- package/dist/create/template/scripts/database.test.ts +0 -121
- package/dist/create/template/scripts/database.ts +0 -105
- package/dist/create/template/src/client/auth.ts +0 -3
- package/dist/create/template/src/client/queries.ts +0 -4
- package/dist/create/template/src/client/queryClient.ts +0 -1
- package/dist/create/template/src/client/useRealtime.ts +0 -20
- package/dist/create/template/src/posthog.ts +0 -21
- package/dist/create/template/src/routeTree.gen.ts +0 -230
- package/dist/create/template/src/router.tsx +0 -17
- package/dist/create/template/src/routes/__root.tsx +0 -40
- package/dist/create/template/src/routes/api/auth.$.ts +0 -8
- package/dist/create/template/src/routes/api/centrifugo.connect.ts +0 -29
- package/dist/create/template/src/routes/api/health.ts +0 -6
- package/dist/create/template/src/routes/api/live.ts +0 -5
- package/dist/create/template/src/routes/api/ready.ts +0 -30
- package/dist/create/template/src/routes/api/uploads.$id.ts +0 -40
- package/dist/create/template/src/routes/api/uploads.ts +0 -25
- package/dist/create/template/src/routes/index.tsx +0 -189
- package/dist/create/template/src/server/app.test.ts +0 -24
- package/dist/create/template/src/server/app.ts +0 -172
- package/dist/create/template/src/server/auth-flow.test.ts +0 -150
- package/dist/create/template/src/server/auth.ts +0 -56
- package/dist/create/template/src/server/environment.test.ts +0 -43
- package/dist/create/template/src/server/environment.ts +0 -67
- package/dist/create/template/src/server/fns.ts +0 -38
- package/dist/create/template/src/server/messages.test.ts +0 -38
- package/dist/create/template/src/server/messages.ts +0 -28
- package/dist/create/template/src/server/migration.test.ts +0 -34
- package/dist/create/template/src/server/outbox.test.ts +0 -130
- package/dist/create/template/src/server/outbox.ts +0 -110
- package/dist/create/template/src/server/posthog.test.ts +0 -34
- package/dist/create/template/src/server/rate-limit.test.ts +0 -32
- package/dist/create/template/src/server/rate-limit.ts +0 -29
- package/dist/create/template/src/server/rpc.ts +0 -16
- package/dist/create/template/src/server/schema.ts +0 -134
- package/dist/create/template/src/server/session.test.ts +0 -56
- package/dist/create/template/src/server/session.ts +0 -13
- package/dist/create/template/src/server/uploads.test.ts +0 -142
- package/dist/create/template/src/server/uploads.ts +0 -199
- package/dist/create/template/src/start.ts +0 -12
- package/dist/create/template/src/styles.css +0 -42
- package/dist/create/template/tsconfig.json +0 -8
- package/dist/create/template/vite.config.ts +0 -31
- package/dist/create/template/vitest.config.ts +0 -3
- package/dist/policy/changesets.js.map +0 -1
- package/dist/policy/cli.d.ts +0 -1
- package/dist/policy/cli.js +0 -23
- package/dist/policy/cli.js.map +0 -1
- package/dist/policy/index.d.ts +0 -14
- package/dist/policy/index.js +0 -132
- package/dist/policy/index.js.map +0 -1
- package/dist/policy/init-cli.d.ts +0 -12
- package/dist/policy/init-cli.js +0 -75
- package/dist/policy/init-cli.js.map +0 -1
- package/dist/policy/init.d.ts +0 -24
- package/dist/policy/init.js +0 -116
- package/dist/policy/init.js.map +0 -1
- package/dist/posthog/coverage.d.ts +0 -23
- package/dist/posthog/coverage.js +0 -30
- package/dist/posthog/coverage.js.map +0 -1
- package/dist/tanstack/query.d.ts +0 -3
- package/dist/tanstack/query.js +0 -8
- package/dist/tanstack/query.js.map +0 -1
- /package/dist/{policy/changesets.d.ts → changesets/index.d.ts} +0 -0
package/dist/policy/cli.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { checkRepositoryPolicy, syncRepositoryPolicy } from './index.js';
|
|
2
|
-
export async function runPolicyCli(arguments_) {
|
|
3
|
-
const [command, extra] = arguments_;
|
|
4
|
-
// `adoption` used to be a second argument. Failing beats quietly running a repository sync somebody did not ask for.
|
|
5
|
-
if ((command !== 'check' && command !== 'sync') || extra !== undefined) {
|
|
6
|
-
console.error('usage: ras policy <check|sync>');
|
|
7
|
-
process.exitCode = 2;
|
|
8
|
-
return;
|
|
9
|
-
}
|
|
10
|
-
const changed = command === 'check' ? await checkRepositoryPolicy(process.cwd()) : await syncRepositoryPolicy(process.cwd(), 'write');
|
|
11
|
-
if (command === 'check' && changed.length > 0) {
|
|
12
|
-
for (const message of changed)
|
|
13
|
-
console.error(message);
|
|
14
|
-
if (changed.some((message) => message.startsWith('policy drift: ')))
|
|
15
|
-
console.error('run ras policy sync and commit the result');
|
|
16
|
-
process.exitCode = 1;
|
|
17
|
-
}
|
|
18
|
-
else if (command === 'sync') {
|
|
19
|
-
for (const path of changed)
|
|
20
|
-
console.log(`updated ${path}`);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
//# sourceMappingURL=cli.js.map
|
package/dist/policy/cli.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/policy/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAExE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,UAAoB;IACrD,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,GAAG,UAAU,CAAA;IACnC,qHAAqH;IACrH,IAAI,CAAC,OAAO,KAAK,OAAO,IAAI,OAAO,KAAK,MAAM,CAAC,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACvE,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAA;QAC/C,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;QACpB,OAAM;IACR,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,qBAAqB,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,oBAAoB,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,CAAA;IACrI,IAAI,OAAO,KAAK,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,KAAK,MAAM,OAAO,IAAI,OAAO;YAAE,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACrD,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAA;QAC/H,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAA;IACtB,CAAC;SAAM,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QAC9B,KAAK,MAAM,IAAI,IAAI,OAAO;YAAE,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAA;IAC5D,CAAC;AACH,CAAC","sourcesContent":["import { checkRepositoryPolicy, syncRepositoryPolicy } from './index.js'\n\nexport async function runPolicyCli(arguments_: string[]): Promise<void> {\n const [command, extra] = arguments_\n // `adoption` used to be a second argument. Failing beats quietly running a repository sync somebody did not ask for.\n if ((command !== 'check' && command !== 'sync') || extra !== undefined) {\n console.error('usage: ras policy <check|sync>')\n process.exitCode = 2\n return\n }\n\n const changed = command === 'check' ? await checkRepositoryPolicy(process.cwd()) : await syncRepositoryPolicy(process.cwd(), 'write')\n if (command === 'check' && changed.length > 0) {\n for (const message of changed) console.error(message)\n if (changed.some((message) => message.startsWith('policy drift: '))) console.error('run ras policy sync and commit the result')\n process.exitCode = 1\n } else if (command === 'sync') {\n for (const path of changed) console.log(`updated ${path}`)\n }\n}\n"]}
|
package/dist/policy/index.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
type PolicySelection = boolean | {
|
|
2
|
-
overrides?: Record<string, unknown>;
|
|
3
|
-
};
|
|
4
|
-
export type RepositoryPolicy = {
|
|
5
|
-
changesets?: PolicySelection;
|
|
6
|
-
dependabot?: PolicySelection;
|
|
7
|
-
pnpm?: false | {
|
|
8
|
-
minimumReleaseAge?: number;
|
|
9
|
-
};
|
|
10
|
-
};
|
|
11
|
-
export declare function syncRepositoryPolicy(root: string, mode: 'check' | 'write'): Promise<string[]>;
|
|
12
|
-
export declare function checkRepositoryPolicy(root: string): Promise<string[]>;
|
|
13
|
-
export declare function renderedPolicyFiles(root: string, config: RepositoryPolicy): Promise<Map<string, string>>;
|
|
14
|
-
export {};
|
package/dist/policy/index.js
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { dirname, join } from 'node:path';
|
|
3
|
-
import { parseDocument, stringify } from 'yaml';
|
|
4
|
-
import { checkChangesets } from './changesets.js';
|
|
5
|
-
const changesetsPolicy = {
|
|
6
|
-
$schema: 'https://unpkg.com/@changesets/config@3.1.2/schema.json',
|
|
7
|
-
changelog: '@changesets/cli/changelog',
|
|
8
|
-
commit: false,
|
|
9
|
-
fixed: [],
|
|
10
|
-
linked: [],
|
|
11
|
-
access: 'restricted',
|
|
12
|
-
privatePackages: { version: true, tag: true },
|
|
13
|
-
baseBranch: 'main',
|
|
14
|
-
updateInternalDependencies: 'patch',
|
|
15
|
-
ignore: [],
|
|
16
|
-
};
|
|
17
|
-
const dependabotPolicy = {
|
|
18
|
-
version: 2,
|
|
19
|
-
updates: [
|
|
20
|
-
{
|
|
21
|
-
'package-ecosystem': 'npm',
|
|
22
|
-
directory: '/',
|
|
23
|
-
schedule: { interval: 'weekly' },
|
|
24
|
-
cooldown: { 'default-days': 7 },
|
|
25
|
-
allow: [
|
|
26
|
-
{
|
|
27
|
-
'dependency-name': '*',
|
|
28
|
-
'update-types': ['version-update:semver-minor', 'version-update:semver-patch'],
|
|
29
|
-
},
|
|
30
|
-
],
|
|
31
|
-
groups: {
|
|
32
|
-
'patch-updates': {
|
|
33
|
-
'applies-to': 'version-updates',
|
|
34
|
-
patterns: ['*'],
|
|
35
|
-
'update-types': ['patch'],
|
|
36
|
-
},
|
|
37
|
-
'minor-updates': {
|
|
38
|
-
'applies-to': 'version-updates',
|
|
39
|
-
patterns: ['*'],
|
|
40
|
-
'update-types': ['minor'],
|
|
41
|
-
},
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
'package-ecosystem': 'github-actions',
|
|
46
|
-
directory: '/',
|
|
47
|
-
schedule: { interval: 'weekly' },
|
|
48
|
-
cooldown: { 'default-days': 7 },
|
|
49
|
-
ignore: [
|
|
50
|
-
{
|
|
51
|
-
'dependency-name': 'richardsolomou/ras-stack*',
|
|
52
|
-
'update-types': ['version-update:semver-major'],
|
|
53
|
-
},
|
|
54
|
-
],
|
|
55
|
-
},
|
|
56
|
-
],
|
|
57
|
-
};
|
|
58
|
-
export async function syncRepositoryPolicy(root, mode) {
|
|
59
|
-
const config = repositoryPolicy(await readFile(join(root, 'ras-stack.policy.json'), 'utf8'));
|
|
60
|
-
const files = await renderedPolicyFiles(root, config);
|
|
61
|
-
const compared = await Promise.all([...files].map(async ([path, expected]) => {
|
|
62
|
-
const absolute = join(root, path);
|
|
63
|
-
const actual = await readFile(absolute, 'utf8').catch(() => undefined);
|
|
64
|
-
if (actual === expected)
|
|
65
|
-
return undefined;
|
|
66
|
-
if (mode === 'write') {
|
|
67
|
-
await mkdir(dirname(absolute), { recursive: true });
|
|
68
|
-
await writeFile(absolute, expected);
|
|
69
|
-
}
|
|
70
|
-
return path;
|
|
71
|
-
}));
|
|
72
|
-
return compared.filter((path) => path !== undefined);
|
|
73
|
-
}
|
|
74
|
-
export async function checkRepositoryPolicy(root) {
|
|
75
|
-
const config = repositoryPolicy(await readFile(join(root, 'ras-stack.policy.json'), 'utf8'));
|
|
76
|
-
const files = await syncRepositoryPolicy(root, 'check');
|
|
77
|
-
return [...files.map((path) => `policy drift: ${path}`), ...(config.changesets ? await checkChangesets(root) : [])];
|
|
78
|
-
}
|
|
79
|
-
export async function renderedPolicyFiles(root, config) {
|
|
80
|
-
const files = new Map();
|
|
81
|
-
if (config.changesets) {
|
|
82
|
-
files.set('.changeset/config.json', `${JSON.stringify(selectedPolicy(changesetsPolicy, config.changesets), null, 2)}\n`);
|
|
83
|
-
}
|
|
84
|
-
if (config.dependabot) {
|
|
85
|
-
files.set('.github/dependabot.yml', stringify(selectedPolicy(dependabotPolicy, config.dependabot), { lineWidth: 0, singleQuote: true }));
|
|
86
|
-
}
|
|
87
|
-
if (config.pnpm) {
|
|
88
|
-
const path = join(root, 'pnpm-workspace.yaml');
|
|
89
|
-
const document = parseDocument(await readFile(path, 'utf8').catch(() => ''));
|
|
90
|
-
document.set('minimumReleaseAge', config.pnpm.minimumReleaseAge ?? 10_080);
|
|
91
|
-
files.set('pnpm-workspace.yaml', document.toString({ lineWidth: 0 }));
|
|
92
|
-
}
|
|
93
|
-
return files;
|
|
94
|
-
}
|
|
95
|
-
function repositoryPolicy(source) {
|
|
96
|
-
const value = JSON.parse(source);
|
|
97
|
-
if (!plainObject(value))
|
|
98
|
-
throw new Error('ras-stack.policy.json must contain an object');
|
|
99
|
-
for (const name of ['changesets', 'dependabot'])
|
|
100
|
-
validateSelection(name, value[name]);
|
|
101
|
-
const pnpm = value.pnpm;
|
|
102
|
-
if (pnpm !== undefined && pnpm !== false) {
|
|
103
|
-
if (!plainObject(pnpm))
|
|
104
|
-
throw new Error('pnpm policy must be false or an object');
|
|
105
|
-
const age = pnpm.minimumReleaseAge;
|
|
106
|
-
if (age !== undefined && (typeof age !== 'number' || !Number.isInteger(age) || age < 0)) {
|
|
107
|
-
throw new Error('pnpm.minimumReleaseAge must be a non-negative integer');
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return value;
|
|
111
|
-
}
|
|
112
|
-
function validateSelection(name, value) {
|
|
113
|
-
if (value === undefined || typeof value === 'boolean')
|
|
114
|
-
return;
|
|
115
|
-
if (!plainObject(value) || (value.overrides !== undefined && !plainObject(value.overrides))) {
|
|
116
|
-
throw new Error(`${name} policy must be a boolean or an object with overrides`);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
function selectedPolicy(base, selection) {
|
|
120
|
-
return selection === true ? base : deepMerge(base, selection.overrides ?? {});
|
|
121
|
-
}
|
|
122
|
-
function deepMerge(base, overrides) {
|
|
123
|
-
return Object.fromEntries([...new Set([...Object.keys(base), ...Object.keys(overrides)])].map((key) => {
|
|
124
|
-
const left = base[key];
|
|
125
|
-
const right = overrides[key];
|
|
126
|
-
return [key, plainObject(left) && plainObject(right) ? deepMerge(left, right) : right === undefined ? left : right];
|
|
127
|
-
}));
|
|
128
|
-
}
|
|
129
|
-
function plainObject(value) {
|
|
130
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
131
|
-
}
|
|
132
|
-
//# sourceMappingURL=index.js.map
|
package/dist/policy/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policy/index.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { parseDocument, stringify } from 'yaml'\nimport { checkChangesets } from './changesets.js'\n\nconst changesetsPolicy = {\n $schema: 'https://unpkg.com/@changesets/config@3.1.2/schema.json',\n changelog: '@changesets/cli/changelog',\n commit: false,\n fixed: [],\n linked: [],\n access: 'restricted',\n privatePackages: { version: true, tag: true },\n baseBranch: 'main',\n updateInternalDependencies: 'patch',\n ignore: [],\n}\n\nconst dependabotPolicy = {\n version: 2,\n updates: [\n {\n 'package-ecosystem': 'npm',\n directory: '/',\n schedule: { interval: 'weekly' },\n cooldown: { 'default-days': 7 },\n allow: [\n {\n 'dependency-name': '*',\n 'update-types': ['version-update:semver-minor', 'version-update:semver-patch'],\n },\n ],\n groups: {\n 'patch-updates': {\n 'applies-to': 'version-updates',\n patterns: ['*'],\n 'update-types': ['patch'],\n },\n 'minor-updates': {\n 'applies-to': 'version-updates',\n patterns: ['*'],\n 'update-types': ['minor'],\n },\n },\n },\n {\n 'package-ecosystem': 'github-actions',\n directory: '/',\n schedule: { interval: 'weekly' },\n cooldown: { 'default-days': 7 },\n ignore: [\n {\n 'dependency-name': 'richardsolomou/ras-stack*',\n 'update-types': ['version-update:semver-major'],\n },\n ],\n },\n ],\n}\n\ntype PolicySelection = boolean | { overrides?: Record<string, unknown> }\n\nexport type RepositoryPolicy = {\n changesets?: PolicySelection\n dependabot?: PolicySelection\n pnpm?: false | { minimumReleaseAge?: number }\n}\n\nexport async function syncRepositoryPolicy(root: string, mode: 'check' | 'write') {\n const config = repositoryPolicy(await readFile(join(root, 'ras-stack.policy.json'), 'utf8'))\n const files = await renderedPolicyFiles(root, config)\n const compared = await Promise.all(\n [...files].map(async ([path, expected]) => {\n const absolute = join(root, path)\n const actual = await readFile(absolute, 'utf8').catch(() => undefined)\n if (actual === expected) return undefined\n if (mode === 'write') {\n await mkdir(dirname(absolute), { recursive: true })\n await writeFile(absolute, expected)\n }\n return path\n }),\n )\n return compared.filter((path) => path !== undefined)\n}\n\nexport async function checkRepositoryPolicy(root: string) {\n const config = repositoryPolicy(await readFile(join(root, 'ras-stack.policy.json'), 'utf8'))\n const files = await syncRepositoryPolicy(root, 'check')\n return [...files.map((path) => `policy drift: ${path}`), ...(config.changesets ? await checkChangesets(root) : [])]\n}\n\nexport async function renderedPolicyFiles(root: string, config: RepositoryPolicy) {\n const files = new Map<string, string>()\n if (config.changesets) {\n files.set('.changeset/config.json', `${JSON.stringify(selectedPolicy(changesetsPolicy, config.changesets), null, 2)}\\n`)\n }\n if (config.dependabot) {\n files.set('.github/dependabot.yml', stringify(selectedPolicy(dependabotPolicy, config.dependabot), { lineWidth: 0, singleQuote: true }))\n }\n if (config.pnpm) {\n const path = join(root, 'pnpm-workspace.yaml')\n const document = parseDocument(await readFile(path, 'utf8').catch(() => ''))\n document.set('minimumReleaseAge', config.pnpm.minimumReleaseAge ?? 10_080)\n files.set('pnpm-workspace.yaml', document.toString({ lineWidth: 0 }))\n }\n return files\n}\n\nfunction repositoryPolicy(source: string): RepositoryPolicy {\n const value = JSON.parse(source) as unknown\n if (!plainObject(value)) throw new Error('ras-stack.policy.json must contain an object')\n for (const name of ['changesets', 'dependabot'] as const) validateSelection(name, value[name])\n const pnpm = value.pnpm\n if (pnpm !== undefined && pnpm !== false) {\n if (!plainObject(pnpm)) throw new Error('pnpm policy must be false or an object')\n const age = pnpm.minimumReleaseAge\n if (age !== undefined && (typeof age !== 'number' || !Number.isInteger(age) || age < 0)) {\n throw new Error('pnpm.minimumReleaseAge must be a non-negative integer')\n }\n }\n return value\n}\n\nfunction validateSelection(name: string, value: unknown) {\n if (value === undefined || typeof value === 'boolean') return\n if (!plainObject(value) || (value.overrides !== undefined && !plainObject(value.overrides))) {\n throw new Error(`${name} policy must be a boolean or an object with overrides`)\n }\n}\n\nfunction selectedPolicy(base: Record<string, unknown>, selection: Exclude<PolicySelection, false>) {\n return selection === true ? base : deepMerge(base, selection.overrides ?? {})\n}\n\nfunction deepMerge(base: Record<string, unknown>, overrides: Record<string, unknown>): Record<string, unknown> {\n return Object.fromEntries(\n [...new Set([...Object.keys(base), ...Object.keys(overrides)])].map((key) => {\n const left = base[key]\n const right = overrides[key]\n return [key, plainObject(left) && plainObject(right) ? deepMerge(left, right) : right === undefined ? left : right]\n }),\n )\n}\n\nfunction plainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n"]}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { type TypeScriptPreset } from './init.js';
|
|
2
|
-
export type InitPrompts = {
|
|
3
|
-
confirm: (options: {
|
|
4
|
-
message: string;
|
|
5
|
-
default: boolean;
|
|
6
|
-
}) => Promise<boolean>;
|
|
7
|
-
select: (options: {
|
|
8
|
-
message: string;
|
|
9
|
-
choices: readonly TypeScriptPreset[];
|
|
10
|
-
}) => Promise<TypeScriptPreset>;
|
|
11
|
-
};
|
|
12
|
-
export declare function runInitCli(arguments_: string[], prompts?: InitPrompts): Promise<void>;
|
package/dist/policy/init-cli.js
DELETED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import confirm from '@inquirer/confirm';
|
|
2
|
-
import select from '@inquirer/select';
|
|
3
|
-
import { applyRepositoryInit, INIT_STEPS, planRepositoryInit } from './init.js';
|
|
4
|
-
const PRESETS = ['library', 'bundler', 'node-bundler', 'browser', 'tanstack'];
|
|
5
|
-
const consolePrompts = {
|
|
6
|
-
confirm: (options) => confirm(options),
|
|
7
|
-
select: (options) => select({ message: options.message, choices: options.choices.map((value) => ({ value })) }),
|
|
8
|
-
};
|
|
9
|
-
export async function runInitCli(arguments_, prompts = consolePrompts) {
|
|
10
|
-
const unknown = arguments_.find((argument) => argument !== '--yes' && argument !== '--dry-run');
|
|
11
|
-
if (unknown) {
|
|
12
|
-
console.error('usage: ras init [--yes] [--dry-run]');
|
|
13
|
-
process.exitCode = 2;
|
|
14
|
-
return;
|
|
15
|
-
}
|
|
16
|
-
const accepted = arguments_.includes('--yes');
|
|
17
|
-
const dryRun = arguments_.includes('--dry-run');
|
|
18
|
-
if (!accepted && prompts === consolePrompts && !process.stdin.isTTY) {
|
|
19
|
-
console.error('ras init asks questions and needs a terminal. Pass --yes to accept every step instead.');
|
|
20
|
-
process.exitCode = 2;
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
try {
|
|
24
|
-
const steps = [];
|
|
25
|
-
let preset = 'library';
|
|
26
|
-
for (const step of INIT_STEPS) {
|
|
27
|
-
// Each step is offered in turn so a repository can adopt one part without the rest.
|
|
28
|
-
// oxlint-disable-next-line no-await-in-loop
|
|
29
|
-
if (!accepted && !(await prompts.confirm({ message: `${step.title}? (${step.detail})`, default: true })))
|
|
30
|
-
continue;
|
|
31
|
-
steps.push(step.name);
|
|
32
|
-
// oxlint-disable-next-line no-await-in-loop
|
|
33
|
-
if (step.name === 'typescript' && !accepted)
|
|
34
|
-
preset = await prompts.select({ message: 'TypeScript preset', choices: PRESETS });
|
|
35
|
-
}
|
|
36
|
-
if (steps.length === 0) {
|
|
37
|
-
console.log('Nothing selected.');
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
const planned = await planRepositoryInit(process.cwd(), { steps, typescriptPreset: preset });
|
|
41
|
-
const writable = accepted ? planned : await confirmOverwrites(prompts, planned);
|
|
42
|
-
if (dryRun) {
|
|
43
|
-
for (const file of writable)
|
|
44
|
-
console.log(`${file.existing === undefined ? 'create' : 'replace'} ${file.path}`);
|
|
45
|
-
console.log('Nothing written because --dry-run was requested.');
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
for (const path of await applyRepositoryInit(process.cwd(), writable))
|
|
49
|
-
console.log(`wrote ${path}`);
|
|
50
|
-
if (steps.includes('policy'))
|
|
51
|
-
console.log('Run ras policy check to confirm the generated files stay in step.');
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
// Ctrl-C during a question is a decision to stop, not a crash worth a stack trace.
|
|
55
|
-
if (error.name !== 'ExitPromptError')
|
|
56
|
-
throw error;
|
|
57
|
-
console.error('Nothing written.');
|
|
58
|
-
process.exitCode = 130;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
async function confirmOverwrites(prompts, planned) {
|
|
62
|
-
const writable = [];
|
|
63
|
-
for (const file of planned) {
|
|
64
|
-
if (file.existing === undefined || file.existing === file.contents) {
|
|
65
|
-
writable.push(file);
|
|
66
|
-
continue;
|
|
67
|
-
}
|
|
68
|
-
// Replacing is the destructive branch, so it is asked one file at a time and defaults to keeping what is there.
|
|
69
|
-
// oxlint-disable-next-line no-await-in-loop
|
|
70
|
-
if (await prompts.confirm({ message: `${file.path} already exists. Replace it?`, default: false }))
|
|
71
|
-
writable.push(file);
|
|
72
|
-
}
|
|
73
|
-
return writable;
|
|
74
|
-
}
|
|
75
|
-
//# sourceMappingURL=init-cli.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"init-cli.js","sourceRoot":"","sources":["../../src/policy/init-cli.ts"],"names":[],"mappings":"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","sourcesContent":["import confirm from '@inquirer/confirm'\nimport select from '@inquirer/select'\nimport { applyRepositoryInit, INIT_STEPS, planRepositoryInit, type InitStepName, type PlannedFile, type TypeScriptPreset } from './init.js'\n\nconst PRESETS: readonly TypeScriptPreset[] = ['library', 'bundler', 'node-bundler', 'browser', 'tanstack']\n\nexport type InitPrompts = {\n confirm: (options: { message: string; default: boolean }) => Promise<boolean>\n select: (options: { message: string; choices: readonly TypeScriptPreset[] }) => Promise<TypeScriptPreset>\n}\n\nconst consolePrompts: InitPrompts = {\n confirm: (options) => confirm(options),\n select: (options) => select({ message: options.message, choices: options.choices.map((value) => ({ value })) }),\n}\n\nexport async function runInitCli(arguments_: string[], prompts: InitPrompts = consolePrompts): Promise<void> {\n const unknown = arguments_.find((argument) => argument !== '--yes' && argument !== '--dry-run')\n if (unknown) {\n console.error('usage: ras init [--yes] [--dry-run]')\n process.exitCode = 2\n return\n }\n const accepted = arguments_.includes('--yes')\n const dryRun = arguments_.includes('--dry-run')\n if (!accepted && prompts === consolePrompts && !process.stdin.isTTY) {\n console.error('ras init asks questions and needs a terminal. Pass --yes to accept every step instead.')\n process.exitCode = 2\n return\n }\n\n try {\n const steps: InitStepName[] = []\n let preset: TypeScriptPreset = 'library'\n for (const step of INIT_STEPS) {\n // Each step is offered in turn so a repository can adopt one part without the rest.\n // oxlint-disable-next-line no-await-in-loop\n if (!accepted && !(await prompts.confirm({ message: `${step.title}? (${step.detail})`, default: true }))) continue\n steps.push(step.name)\n // oxlint-disable-next-line no-await-in-loop\n if (step.name === 'typescript' && !accepted) preset = await prompts.select({ message: 'TypeScript preset', choices: PRESETS })\n }\n if (steps.length === 0) {\n console.log('Nothing selected.')\n return\n }\n\n const planned = await planRepositoryInit(process.cwd(), { steps, typescriptPreset: preset })\n const writable = accepted ? planned : await confirmOverwrites(prompts, planned)\n\n if (dryRun) {\n for (const file of writable) console.log(`${file.existing === undefined ? 'create' : 'replace'} ${file.path}`)\n console.log('Nothing written because --dry-run was requested.')\n return\n }\n\n for (const path of await applyRepositoryInit(process.cwd(), writable)) console.log(`wrote ${path}`)\n if (steps.includes('policy')) console.log('Run ras policy check to confirm the generated files stay in step.')\n } catch (error) {\n // Ctrl-C during a question is a decision to stop, not a crash worth a stack trace.\n if ((error as { name?: string }).name !== 'ExitPromptError') throw error\n console.error('Nothing written.')\n process.exitCode = 130\n }\n}\n\nasync function confirmOverwrites(prompts: InitPrompts, planned: readonly PlannedFile[]) {\n const writable: PlannedFile[] = []\n for (const file of planned) {\n if (file.existing === undefined || file.existing === file.contents) {\n writable.push(file)\n continue\n }\n // Replacing is the destructive branch, so it is asked one file at a time and defaults to keeping what is there.\n // oxlint-disable-next-line no-await-in-loop\n if (await prompts.confirm({ message: `${file.path} already exists. Replace it?`, default: false })) writable.push(file)\n }\n return writable\n}\n"]}
|
package/dist/policy/init.d.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export type InitStepName = 'policy' | 'toolchain' | 'typescript' | 'oxlint' | 'workflow' | 'justfile';
|
|
2
|
-
export type InitStep = {
|
|
3
|
-
name: InitStepName;
|
|
4
|
-
title: string;
|
|
5
|
-
detail: string;
|
|
6
|
-
};
|
|
7
|
-
export type TypeScriptPreset = 'library' | 'bundler' | 'node-bundler' | 'browser' | 'tanstack';
|
|
8
|
-
export type InitAnswers = {
|
|
9
|
-
steps: readonly InitStepName[];
|
|
10
|
-
typescriptPreset?: TypeScriptPreset;
|
|
11
|
-
};
|
|
12
|
-
export type PlannedFile = {
|
|
13
|
-
path: string;
|
|
14
|
-
contents: string;
|
|
15
|
-
existing?: string;
|
|
16
|
-
};
|
|
17
|
-
export declare const INIT_TOOLCHAIN: {
|
|
18
|
-
node: string;
|
|
19
|
-
pnpm: string;
|
|
20
|
-
just: string;
|
|
21
|
-
};
|
|
22
|
-
export declare const INIT_STEPS: readonly InitStep[];
|
|
23
|
-
export declare function planRepositoryInit(root: string, answers: InitAnswers): Promise<PlannedFile[]>;
|
|
24
|
-
export declare function applyRepositoryInit(root: string, files: readonly PlannedFile[]): Promise<string[]>;
|
package/dist/policy/init.js
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
-
import { dirname, join } from 'node:path';
|
|
3
|
-
import { renderedPolicyFiles } from './index.js';
|
|
4
|
-
// Toolchain a generated repository starts on. `init.test.ts` holds these to what this repository itself runs.
|
|
5
|
-
export const INIT_TOOLCHAIN = {
|
|
6
|
-
node: '>=24 <25',
|
|
7
|
-
pnpm: '11.15.0',
|
|
8
|
-
just: '1.58.0',
|
|
9
|
-
};
|
|
10
|
-
export const INIT_STEPS = [
|
|
11
|
-
{
|
|
12
|
-
name: 'policy',
|
|
13
|
-
title: 'Repository policy',
|
|
14
|
-
detail: 'ras-stack.policy.json plus the Changesets, Dependabot, and pnpm files it generates',
|
|
15
|
-
},
|
|
16
|
-
{ name: 'toolchain', title: 'Toolchain versions', detail: 'engines.node and packageManager in package.json' },
|
|
17
|
-
{ name: 'typescript', title: 'TypeScript configuration', detail: 'tsconfig.json extending a shared preset' },
|
|
18
|
-
{ name: 'oxlint', title: 'Lint configuration', detail: '.oxlintrc.json extending the shared rules' },
|
|
19
|
-
{ name: 'workflow', title: 'CI workflow', detail: '.github/workflows/ci.yml calling the shared check workflow' },
|
|
20
|
-
{ name: 'justfile', title: 'Command runner', detail: 'justfile wrapping the package scripts' },
|
|
21
|
-
];
|
|
22
|
-
export async function planRepositoryInit(root, answers) {
|
|
23
|
-
const selected = new Set(answers.steps);
|
|
24
|
-
const planned = [];
|
|
25
|
-
if (selected.has('policy')) {
|
|
26
|
-
const policy = { changesets: true, dependabot: true, pnpm: {} };
|
|
27
|
-
planned.push({ path: 'ras-stack.policy.json', contents: `${JSON.stringify(policy, null, 2)}\n` });
|
|
28
|
-
for (const [path, contents] of await renderedPolicyFiles(root, policy))
|
|
29
|
-
planned.push({ path, contents });
|
|
30
|
-
}
|
|
31
|
-
if (selected.has('toolchain')) {
|
|
32
|
-
const manifest = await readJson(join(root, 'package.json'));
|
|
33
|
-
if (!manifest)
|
|
34
|
-
throw new Error('package.json is required before the toolchain can be configured');
|
|
35
|
-
const engines = manifest.engines && typeof manifest.engines === 'object' ? manifest.engines : {};
|
|
36
|
-
const configured = { ...manifest, engines: { ...engines, node: INIT_TOOLCHAIN.node }, packageManager: `pnpm@${INIT_TOOLCHAIN.pnpm}` };
|
|
37
|
-
planned.push({ path: 'package.json', contents: `${JSON.stringify(configured, null, 2)}\n` });
|
|
38
|
-
}
|
|
39
|
-
if (selected.has('typescript')) {
|
|
40
|
-
const preset = answers.typescriptPreset ?? 'library';
|
|
41
|
-
planned.push({
|
|
42
|
-
path: 'tsconfig.json',
|
|
43
|
-
contents: `${JSON.stringify({ extends: `./node_modules/ras-stack/config/typescript/${preset}.json`, compilerOptions: { types: ['node'] }, include: ['src/**/*.ts'] }, null, 2)}\n`,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
if (selected.has('oxlint')) {
|
|
47
|
-
planned.push({
|
|
48
|
-
path: '.oxlintrc.json',
|
|
49
|
-
contents: `${JSON.stringify({ extends: ['./node_modules/ras-stack/config/oxlint.json'] }, null, 2)}\n`,
|
|
50
|
-
});
|
|
51
|
-
}
|
|
52
|
-
if (selected.has('workflow'))
|
|
53
|
-
planned.push({ path: '.github/workflows/ci.yml', contents: workflow() });
|
|
54
|
-
if (selected.has('justfile'))
|
|
55
|
-
planned.push({ path: 'justfile', contents: JUSTFILE });
|
|
56
|
-
await Promise.all(planned.map(async (file) => {
|
|
57
|
-
const existing = await readFile(join(root, file.path), 'utf8').catch(() => undefined);
|
|
58
|
-
if (existing !== undefined)
|
|
59
|
-
file.existing = existing;
|
|
60
|
-
}));
|
|
61
|
-
return planned;
|
|
62
|
-
}
|
|
63
|
-
export async function applyRepositoryInit(root, files) {
|
|
64
|
-
await Promise.all(files.map(async (file) => {
|
|
65
|
-
const absolute = join(root, file.path);
|
|
66
|
-
await mkdir(dirname(absolute), { recursive: true });
|
|
67
|
-
await writeFile(absolute, file.contents);
|
|
68
|
-
}));
|
|
69
|
-
return files.map((file) => file.path);
|
|
70
|
-
}
|
|
71
|
-
function workflow() {
|
|
72
|
-
return `name: CI
|
|
73
|
-
|
|
74
|
-
on:
|
|
75
|
-
pull_request:
|
|
76
|
-
push:
|
|
77
|
-
branches: [main]
|
|
78
|
-
|
|
79
|
-
permissions:
|
|
80
|
-
contents: read
|
|
81
|
-
|
|
82
|
-
jobs:
|
|
83
|
-
check:
|
|
84
|
-
uses: richardsolomou/ras-stack/.github/workflows/check-js.yml@v1
|
|
85
|
-
with:
|
|
86
|
-
command: just check
|
|
87
|
-
just-version: '${INIT_TOOLCHAIN.just}'
|
|
88
|
-
`;
|
|
89
|
-
}
|
|
90
|
-
const JUSTFILE = `default:
|
|
91
|
-
@just --list
|
|
92
|
-
|
|
93
|
-
install:
|
|
94
|
-
corepack enable
|
|
95
|
-
pnpm install
|
|
96
|
-
|
|
97
|
-
format:
|
|
98
|
-
pnpm format
|
|
99
|
-
|
|
100
|
-
lint:
|
|
101
|
-
pnpm lint
|
|
102
|
-
|
|
103
|
-
typecheck:
|
|
104
|
-
pnpm typecheck
|
|
105
|
-
|
|
106
|
-
test *args:
|
|
107
|
-
pnpm exec vitest run {{ args }}
|
|
108
|
-
|
|
109
|
-
check:
|
|
110
|
-
pnpm check
|
|
111
|
-
`;
|
|
112
|
-
async function readJson(path) {
|
|
113
|
-
const source = await readFile(path, 'utf8').catch(() => undefined);
|
|
114
|
-
return source === undefined ? undefined : JSON.parse(source);
|
|
115
|
-
}
|
|
116
|
-
//# sourceMappingURL=init.js.map
|
package/dist/policy/init.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/policy/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { renderedPolicyFiles } from './index.js'\n\nexport type InitStepName = 'policy' | 'toolchain' | 'typescript' | 'oxlint' | 'workflow' | 'justfile'\n\nexport type InitStep = { name: InitStepName; title: string; detail: string }\n\nexport type TypeScriptPreset = 'library' | 'bundler' | 'node-bundler' | 'browser' | 'tanstack'\n\nexport type InitAnswers = { steps: readonly InitStepName[]; typescriptPreset?: TypeScriptPreset }\n\nexport type PlannedFile = { path: string; contents: string; existing?: string }\n\n// Toolchain a generated repository starts on. `init.test.ts` holds these to what this repository itself runs.\nexport const INIT_TOOLCHAIN = {\n node: '>=24 <25',\n pnpm: '11.15.0',\n just: '1.58.0',\n}\n\nexport const INIT_STEPS: readonly InitStep[] = [\n {\n name: 'policy',\n title: 'Repository policy',\n detail: 'ras-stack.policy.json plus the Changesets, Dependabot, and pnpm files it generates',\n },\n { name: 'toolchain', title: 'Toolchain versions', detail: 'engines.node and packageManager in package.json' },\n { name: 'typescript', title: 'TypeScript configuration', detail: 'tsconfig.json extending a shared preset' },\n { name: 'oxlint', title: 'Lint configuration', detail: '.oxlintrc.json extending the shared rules' },\n { name: 'workflow', title: 'CI workflow', detail: '.github/workflows/ci.yml calling the shared check workflow' },\n { name: 'justfile', title: 'Command runner', detail: 'justfile wrapping the package scripts' },\n]\n\nexport async function planRepositoryInit(root: string, answers: InitAnswers): Promise<PlannedFile[]> {\n const selected = new Set(answers.steps)\n const planned: PlannedFile[] = []\n\n if (selected.has('policy')) {\n const policy = { changesets: true, dependabot: true, pnpm: {} }\n planned.push({ path: 'ras-stack.policy.json', contents: `${JSON.stringify(policy, null, 2)}\\n` })\n for (const [path, contents] of await renderedPolicyFiles(root, policy)) planned.push({ path, contents })\n }\n\n if (selected.has('toolchain')) {\n const manifest = await readJson(join(root, 'package.json'))\n if (!manifest) throw new Error('package.json is required before the toolchain can be configured')\n const engines = manifest.engines && typeof manifest.engines === 'object' ? manifest.engines : {}\n const configured = { ...manifest, engines: { ...engines, node: INIT_TOOLCHAIN.node }, packageManager: `pnpm@${INIT_TOOLCHAIN.pnpm}` }\n planned.push({ path: 'package.json', contents: `${JSON.stringify(configured, null, 2)}\\n` })\n }\n\n if (selected.has('typescript')) {\n const preset = answers.typescriptPreset ?? 'library'\n planned.push({\n path: 'tsconfig.json',\n contents: `${JSON.stringify({ extends: `./node_modules/ras-stack/config/typescript/${preset}.json`, compilerOptions: { types: ['node'] }, include: ['src/**/*.ts'] }, null, 2)}\\n`,\n })\n }\n\n if (selected.has('oxlint')) {\n planned.push({\n path: '.oxlintrc.json',\n contents: `${JSON.stringify({ extends: ['./node_modules/ras-stack/config/oxlint.json'] }, null, 2)}\\n`,\n })\n }\n\n if (selected.has('workflow')) planned.push({ path: '.github/workflows/ci.yml', contents: workflow() })\n if (selected.has('justfile')) planned.push({ path: 'justfile', contents: JUSTFILE })\n\n await Promise.all(\n planned.map(async (file) => {\n const existing = await readFile(join(root, file.path), 'utf8').catch(() => undefined)\n if (existing !== undefined) file.existing = existing\n }),\n )\n return planned\n}\n\nexport async function applyRepositoryInit(root: string, files: readonly PlannedFile[]) {\n await Promise.all(\n files.map(async (file) => {\n const absolute = join(root, file.path)\n await mkdir(dirname(absolute), { recursive: true })\n await writeFile(absolute, file.contents)\n }),\n )\n return files.map((file) => file.path)\n}\n\nfunction workflow() {\n return `name: CI\n\non:\n pull_request:\n push:\n branches: [main]\n\npermissions:\n contents: read\n\njobs:\n check:\n uses: richardsolomou/ras-stack/.github/workflows/check-js.yml@v1\n with:\n command: just check\n just-version: '${INIT_TOOLCHAIN.just}'\n`\n}\n\nconst JUSTFILE = `default:\n @just --list\n\ninstall:\n corepack enable\n pnpm install\n\nformat:\n pnpm format\n\nlint:\n pnpm lint\n\ntypecheck:\n pnpm typecheck\n\ntest *args:\n pnpm exec vitest run {{ args }}\n\ncheck:\n pnpm check\n`\n\nasync function readJson(path: string | URL) {\n const source = await readFile(path, 'utf8').catch(() => undefined)\n return source === undefined ? undefined : (JSON.parse(source) as Record<string, unknown>)\n}\n"]}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
export type PostHogCoverageDecision = true | {
|
|
2
|
-
disabled: string;
|
|
3
|
-
};
|
|
4
|
-
export type PostHogCoverage = {
|
|
5
|
-
browser: {
|
|
6
|
-
analytics: PostHogCoverageDecision;
|
|
7
|
-
errorTracking: PostHogCoverageDecision;
|
|
8
|
-
featureFlags: PostHogCoverageDecision;
|
|
9
|
-
identity: PostHogCoverageDecision;
|
|
10
|
-
logs?: PostHogCoverageDecision;
|
|
11
|
-
metrics?: PostHogCoverageDecision;
|
|
12
|
-
sessionReplay: PostHogCoverageDecision;
|
|
13
|
-
};
|
|
14
|
-
server: {
|
|
15
|
-
analytics: PostHogCoverageDecision;
|
|
16
|
-
errorTracking: PostHogCoverageDecision;
|
|
17
|
-
logs: PostHogCoverageDecision;
|
|
18
|
-
metrics?: PostHogCoverageDecision;
|
|
19
|
-
tracing?: PostHogCoverageDecision;
|
|
20
|
-
};
|
|
21
|
-
sourceMaps: PostHogCoverageDecision;
|
|
22
|
-
};
|
|
23
|
-
export declare function definePostHogCoverage(coverage: PostHogCoverage): PostHogCoverage;
|
package/dist/posthog/coverage.js
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export function definePostHogCoverage(coverage) {
|
|
2
|
-
for (const [area, decision] of coverageDecisions(coverage)) {
|
|
3
|
-
if (decision === true)
|
|
4
|
-
continue;
|
|
5
|
-
if (!decision || typeof decision !== 'object' || typeof decision.disabled !== 'string') {
|
|
6
|
-
throw new Error(`${area} must be enabled or include a disabled reason`);
|
|
7
|
-
}
|
|
8
|
-
if (!decision.disabled.trim())
|
|
9
|
-
throw new Error(`${area} disabled reason must not be empty`);
|
|
10
|
-
}
|
|
11
|
-
return coverage;
|
|
12
|
-
}
|
|
13
|
-
function coverageDecisions(coverage) {
|
|
14
|
-
return [
|
|
15
|
-
['browser.analytics', coverage.browser.analytics],
|
|
16
|
-
['browser.errorTracking', coverage.browser.errorTracking],
|
|
17
|
-
['browser.featureFlags', coverage.browser.featureFlags],
|
|
18
|
-
['browser.identity', coverage.browser.identity],
|
|
19
|
-
...(coverage.browser.logs ? [['browser.logs', coverage.browser.logs]] : []),
|
|
20
|
-
...(coverage.browser.metrics ? [['browser.metrics', coverage.browser.metrics]] : []),
|
|
21
|
-
['browser.sessionReplay', coverage.browser.sessionReplay],
|
|
22
|
-
['server.analytics', coverage.server.analytics],
|
|
23
|
-
['server.errorTracking', coverage.server.errorTracking],
|
|
24
|
-
['server.logs', coverage.server.logs],
|
|
25
|
-
...(coverage.server.metrics ? [['server.metrics', coverage.server.metrics]] : []),
|
|
26
|
-
...(coverage.server.tracing ? [['server.tracing', coverage.server.tracing]] : []),
|
|
27
|
-
['sourceMaps', coverage.sourceMaps],
|
|
28
|
-
];
|
|
29
|
-
}
|
|
30
|
-
//# sourceMappingURL=coverage.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/posthog/coverage.ts"],"names":[],"mappings":"AAsBA,MAAM,UAAU,qBAAqB,CAAC,QAAyB;IAC7D,KAAK,MAAM,CAAC,IAAI,EAAE,QAAQ,CAAC,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3D,IAAI,QAAQ,KAAK,IAAI;YAAE,SAAQ;QAC/B,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACvF,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,+CAA+C,CAAC,CAAA;QACzE,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oCAAoC,CAAC,CAAA;IAC7F,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,iBAAiB,CAAC,QAAyB;IAClD,OAAO;QACL,CAAC,mBAAmB,EAAE,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC;QACjD,CAAC,uBAAuB,EAAE,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC;QACzD,CAAC,sBAAsB,EAAE,QAAQ,CAAC,OAAO,CAAC,YAAY,CAAC;QACvD,CAAC,kBAAkB,EAAE,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC;QAC/C,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAE,CAAC,CAAC,cAAc,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAA8C,CAAC,CAAC,CAAC,EAAE,CAAC;QACzH,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,iBAAiB,EAAE,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAA8C,CAAC,CAAC,CAAC,EAAE,CAAC;QAClI,CAAC,uBAAuB,EAAE,QAAQ,CAAC,OAAO,CAAC,aAAa,CAAC;QACzD,CAAC,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;QAC/C,CAAC,sBAAsB,EAAE,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC;QACvD,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;QACrC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAA8C,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/H,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,CAAC,gBAAgB,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAA8C,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/H,CAAC,YAAY,EAAE,QAAQ,CAAC,UAAU,CAAC;KACpC,CAAA;AACH,CAAC","sourcesContent":["export type PostHogCoverageDecision = true | { disabled: string }\n\nexport type PostHogCoverage = {\n browser: {\n analytics: PostHogCoverageDecision\n errorTracking: PostHogCoverageDecision\n featureFlags: PostHogCoverageDecision\n identity: PostHogCoverageDecision\n logs?: PostHogCoverageDecision\n metrics?: PostHogCoverageDecision\n sessionReplay: PostHogCoverageDecision\n }\n server: {\n analytics: PostHogCoverageDecision\n errorTracking: PostHogCoverageDecision\n logs: PostHogCoverageDecision\n metrics?: PostHogCoverageDecision\n tracing?: PostHogCoverageDecision\n }\n sourceMaps: PostHogCoverageDecision\n}\n\nexport function definePostHogCoverage(coverage: PostHogCoverage) {\n for (const [area, decision] of coverageDecisions(coverage)) {\n if (decision === true) continue\n if (!decision || typeof decision !== 'object' || typeof decision.disabled !== 'string') {\n throw new Error(`${area} must be enabled or include a disabled reason`)\n }\n if (!decision.disabled.trim()) throw new Error(`${area} disabled reason must not be empty`)\n }\n return coverage\n}\n\nfunction coverageDecisions(coverage: PostHogCoverage): Array<[string, PostHogCoverageDecision]> {\n return [\n ['browser.analytics', coverage.browser.analytics],\n ['browser.errorTracking', coverage.browser.errorTracking],\n ['browser.featureFlags', coverage.browser.featureFlags],\n ['browser.identity', coverage.browser.identity],\n ...(coverage.browser.logs ? ([['browser.logs', coverage.browser.logs]] as Array<[string, PostHogCoverageDecision]>) : []),\n ...(coverage.browser.metrics ? ([['browser.metrics', coverage.browser.metrics]] as Array<[string, PostHogCoverageDecision]>) : []),\n ['browser.sessionReplay', coverage.browser.sessionReplay],\n ['server.analytics', coverage.server.analytics],\n ['server.errorTracking', coverage.server.errorTracking],\n ['server.logs', coverage.server.logs],\n ...(coverage.server.metrics ? ([['server.metrics', coverage.server.metrics]] as Array<[string, PostHogCoverageDecision]>) : []),\n ...(coverage.server.tracing ? ([['server.tracing', coverage.server.tracing]] as Array<[string, PostHogCoverageDecision]>) : []),\n ['sourceMaps', coverage.sourceMaps],\n ]\n}\n"]}
|
package/dist/tanstack/query.d.ts
DELETED
package/dist/tanstack/query.js
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { QueryClient } from '@tanstack/react-query';
|
|
2
|
-
export function createStackQueryClient(config = {}) {
|
|
3
|
-
return new QueryClient({ defaultOptions: { queries: { staleTime: 1000 } }, ...config });
|
|
4
|
-
}
|
|
5
|
-
export function queryErrorMessage(error, fallback = 'Something went wrong. Try again.') {
|
|
6
|
-
return error instanceof Error && error.message ? error.message : fallback;
|
|
7
|
-
}
|
|
8
|
-
//# sourceMappingURL=query.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"query.js","sourceRoot":"","sources":["../../src/tanstack/query.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAA0B,MAAM,uBAAuB,CAAA;AAE3E,MAAM,UAAU,sBAAsB,CAAC,MAAM,GAAsB,EAAE;IACnE,OAAO,IAAI,WAAW,CAAC,EAAE,cAAc,EAAE,EAAE,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC,CAAA;AACzF,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAc,EAAE,QAAQ,GAAG,kCAAkC;IAC7F,OAAO,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAA;AAC3E,CAAC","sourcesContent":["import { QueryClient, type QueryClientConfig } from '@tanstack/react-query'\n\nexport function createStackQueryClient(config: QueryClientConfig = {}) {\n return new QueryClient({ defaultOptions: { queries: { staleTime: 1000 } }, ...config })\n}\n\nexport function queryErrorMessage(error: unknown, fallback = 'Something went wrong. Try again.') {\n return error instanceof Error && error.message ? error.message : fallback\n}\n"]}
|
|
File without changes
|