@cedarjs/auth-firebase-setup 0.0.4

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Cedar
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # Authentication
2
+
3
+ ## Contributing
4
+
5
+ If you want to contribute a new auth provider integration we recommend you
6
+ start by implementing it as a custom auth provider in a Redwood App first. When
7
+ that works you can package it up as an npm package and publish it on your own.
8
+ You can then create a PR on this repo with support for your new auth provider
9
+ in our `yarn rw setup auth` cli command. The easiest option is probably to just
10
+ look at one of the existing auth providers in
11
+ `packages/cli/src/commands/setup/auth/providers` and the corresponding
12
+ templates in `../templates`.
13
+
14
+ If you need help setting up a custom auth provider you can read the auth docs
15
+ on the web.
16
+
17
+ ### Contributing to the base auth implementation
18
+
19
+ If you want to contribute to our auth implementation, the interface towards
20
+ both auth service providers and RW apps we recommend you start looking in
21
+ `authFactory.ts` and then continue to `AuthProvider.tsx`. `AuthProvider.tsx`
22
+ has most of our implementation together with all the custom hooks it uses.
23
+ Another file to be accustomed with is `AuthContext.ts`. The interface in there
24
+ has pretty good code comments, and is what will be exposed to RW apps.
25
+
26
+ ## getCurrentUser
27
+
28
+ `getCurrentUser` returns the user information together with
29
+ an optional collection of roles used by requireAuth() to check if the user is authenticated or has role-based access.
30
+
31
+ Use in conjunction with `requireAuth` in your services to check that a user is logged in, whether or not they are assigned a role, and optionally raise an error if they're not.
32
+
33
+ ```js
34
+ @param decoded - The decoded access token containing user info and JWT claims like `sub`
35
+ @param { token, SupportedAuthTypes type } - The access token itself as well as the auth provider type
36
+ @param { APIGatewayEvent event, Context context } - An object which contains information from the invoker
37
+ such as headers and cookies, and the context information about the invocation such as IP Address
38
+ ```
39
+
40
+ ### Examples
41
+
42
+ #### Checks if currentUser is authenticated
43
+
44
+ This example is the standard use of `getCurrentUser`.
45
+
46
+ ```js
47
+ export const getCurrentUser = async (
48
+ decoded,
49
+ { _token, _type },
50
+ { _event, _context },
51
+ ) => {
52
+ return { ...decoded, roles: parseJWT({ decoded }).roles }
53
+ }
54
+ ```
55
+
56
+ #### User details fetched via database query
57
+
58
+ ```js
59
+ export const getCurrentUser = async (decoded) => {
60
+ return await db.user.findUnique({ where: { decoded.email } })
61
+ }
62
+ ```
63
+
64
+ #### User info is decoded from the access token
65
+
66
+ ```js
67
+ export const getCurrentUser = async (decoded) => {
68
+ return { ...decoded }
69
+ }
70
+ ```
71
+
72
+ #### User info is contained in the decoded token and roles extracted
73
+
74
+ ```js
75
+ export const getCurrentUser = async (decoded) => {
76
+ return { ...decoded, roles: parseJWT({ decoded }).roles }
77
+ }
78
+ ```
79
+
80
+ #### User record query by email with namespaced app_metadata roles as Auth0 requires custom JWT claims to be namespaced
81
+
82
+ ```js
83
+ export const getCurrentUser = async (decoded) => {
84
+ const currentUser = await db.user.findUnique({
85
+ where: { email: decoded.email },
86
+ })
87
+
88
+ return {
89
+ ...currentUser,
90
+ roles: parseJWT({ decoded: decoded, namespace: NAMESPACE }).roles,
91
+ }
92
+ }
93
+ ```
94
+
95
+ #### User record query by an identity with app_metadata roles
96
+
97
+ ```js
98
+ const getCurrentUser = async (decoded) => {
99
+ const currentUser = await db.user.findUnique({
100
+ where: { userIdentity: decoded.sub },
101
+ })
102
+ return {
103
+ ...currentUser,
104
+ roles: parseJWT({ decoded: decoded }).roles,
105
+ }
106
+ }
107
+ ```
108
+
109
+ #### Cookies and other request information are available in the req parameter, just in case
110
+
111
+ ```js
112
+ const getCurrentUser = async (_decoded, _raw, { event, _context }) => {
113
+ const cookies = cookie(event.headers.cookies)
114
+ const session = cookies['my.cookie.name']
115
+ const currentUser = await db.sessions.findUnique({ where: { id: session } })
116
+ return currentUser
117
+ }
118
+ ```
119
+
120
+ ## requireAuth
121
+
122
+ Use `requireAuth` in your services to check that a user is logged in, whether or not they are assigned a role, and optionally raise an error if they're not.
123
+
124
+ ```js
125
+ @param {string=} roles - An optional role or list of roles
126
+ @param {string[]=} roles - An optional list of roles
127
+
128
+ @returns {boolean} - If the currentUser is authenticated (and assigned one of the given roles)
129
+
130
+ @throws {AuthenticationError} - If the currentUser is not authenticated
131
+ @throws {ForbiddenError} If the currentUser is not allowed due to role permissions
132
+ ```
133
+
134
+ ### Examples
135
+
136
+ #### Checks if currentUser is authenticated
137
+
138
+ ```js
139
+ requireAuth()
140
+ ```
141
+
142
+ #### Checks if currentUser is authenticated and assigned one of the given roles
143
+
144
+ ```js
145
+ requireAuth({ role: 'admin' })
146
+ requireAuth({ role: ['editor', 'author'] })
147
+ requireAuth({ role: ['publisher'] })
148
+ ```
@@ -0,0 +1,2 @@
1
+ export * from './setup';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __copyProps = (to, from, except, desc) => {
7
+ if (from && typeof from === "object" || typeof from === "function") {
8
+ for (let key of __getOwnPropNames(from))
9
+ if (!__hasOwnProp.call(to, key) && key !== except)
10
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
+ }
12
+ return to;
13
+ };
14
+ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
15
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
16
+ var index_exports = {};
17
+ module.exports = __toCommonJS(index_exports);
18
+ __reExport(index_exports, require("./setup"), module.exports);
19
+ // Annotate the CommonJS export names for ESM import in node:
20
+ 0 && (module.exports = {
21
+ ...require("./setup")
22
+ });
@@ -0,0 +1,13 @@
1
+ import type yargs from 'yargs';
2
+ export declare const command = "firebase";
3
+ export declare const description = "Set up auth for for Firebase";
4
+ export declare function builder(yargs: yargs.Argv): yargs.Argv<{
5
+ force: boolean;
6
+ } & {
7
+ verbose: boolean;
8
+ }>;
9
+ export interface Args {
10
+ force: boolean;
11
+ }
12
+ export declare function handler(options: Args): Promise<void>;
13
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../src/setup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAI9B,eAAO,MAAM,OAAO,aAAa,CAAA;AACjC,eAAO,MAAM,WAAW,iCAAiC,CAAA;AAEzD,wBAAgB,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI;;;;GAExC;AAED,MAAM,WAAW,IAAI;IACnB,KAAK,EAAE,OAAO,CAAA;CACf;AAED,wBAAsB,OAAO,CAAC,OAAO,EAAE,IAAI,iBAG1C"}
package/dist/setup.js ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var setup_exports = {};
30
+ __export(setup_exports, {
31
+ builder: () => builder,
32
+ command: () => command,
33
+ description: () => description,
34
+ handler: () => handler
35
+ });
36
+ module.exports = __toCommonJS(setup_exports);
37
+ var import_cli_helpers = require("@cedarjs/cli-helpers");
38
+ const command = "firebase";
39
+ const description = "Set up auth for for Firebase";
40
+ function builder(yargs) {
41
+ return (0, import_cli_helpers.standardAuthBuilder)(yargs);
42
+ }
43
+ async function handler(options) {
44
+ const { handler: handler2 } = await import("./setupHandler.js");
45
+ return handler2(options);
46
+ }
47
+ // Annotate the CommonJS export names for ESM import in node:
48
+ 0 && (module.exports = {
49
+ builder,
50
+ command,
51
+ description,
52
+ handler
53
+ });
@@ -0,0 +1,3 @@
1
+ import type { Args } from './setup';
2
+ export declare function handler({ force: forceArg }: Args): Promise<void>;
3
+ //# sourceMappingURL=setupHandler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setupHandler.d.ts","sourceRoot":"","sources":["../src/setupHandler.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAMnC,wBAAsB,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,IAAI,iBAmCtD"}
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var setupHandler_exports = {};
30
+ __export(setupHandler_exports, {
31
+ handler: () => handler
32
+ });
33
+ module.exports = __toCommonJS(setupHandler_exports);
34
+ var import_fs = __toESM(require("fs"));
35
+ var import_path = __toESM(require("path"));
36
+ var import_cli_helpers = require("@cedarjs/cli-helpers");
37
+ const { version } = JSON.parse(
38
+ import_fs.default.readFileSync(import_path.default.resolve(__dirname, "../package.json"), "utf-8")
39
+ );
40
+ async function handler({ force: forceArg }) {
41
+ (0, import_cli_helpers.standardAuthHandler)({
42
+ basedir: __dirname,
43
+ forceArg,
44
+ provider: "firebase",
45
+ authDecoderImport: "import { authDecoder } from '@cedarjs/auth-firebase-api'",
46
+ webPackages: ["firebase@^10", `@cedarjs/auth-firebase-web@${version}`],
47
+ apiPackages: [
48
+ // Note that the version of this package should be exactly the same as the version in `@cedarjs/auth-firebase-api` .
49
+ "firebase-admin@12.1.1",
50
+ `@cedarjs/auth-firebase-api@${version}`
51
+ ],
52
+ notes: [
53
+ "You'll need to add three env vars to your .env file:",
54
+ "",
55
+ '```bash title=".env"',
56
+ 'FIREBASE_API_KEY="..."',
57
+ 'FIREBASE_AUTH_DOMAIN="..."',
58
+ 'FIREBASE_PROJECT_ID="..."',
59
+ "```",
60
+ "",
61
+ "You can find their values on your Firebase app's dashboard.",
62
+ "Be sure to include `FIREBASE_API_KEY` and `FIREBASE_AUTH_DOMAIN` in the `includeEnvironmentVariables` array in redwood.toml:",
63
+ "",
64
+ '```toml title="redwood.toml"',
65
+ "includeEnvironmentVariables = [",
66
+ ' "FIREBASE_API_KEY",',
67
+ ' "FIREBASE_AUTH_DOMAIN"',
68
+ "]",
69
+ "```",
70
+ "",
71
+ "Also see https://redwoodjs.com/docs/auth/firebase for a full walkthrough."
72
+ ]
73
+ });
74
+ }
75
+ // Annotate the CommonJS export names for ESM import in node:
76
+ 0 && (module.exports = {
77
+ handler
78
+ });
@@ -0,0 +1,62 @@
1
+ import admin from 'firebase-admin'
2
+
3
+ import { AuthenticationError } from '@cedarjs/graphql-server'
4
+
5
+ // eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars
6
+ const adminApp = admin.initializeApp({
7
+ projectId: process.env.FIREBASE_PROJECT_ID,
8
+ })
9
+
10
+ /**
11
+ * getCurrentUser returns the user information from the decoded JWT
12
+ *
13
+ * @param decoded - The decoded access token containing user info and JWT claims like `sub`. Note could be null.
14
+ * @param { token, SupportedAuthTypes type } - The access token itself as well as the auth provider type
15
+ * @param { APIGatewayEvent event, Context context } - An object which contains information from the invoker
16
+ * such as headers and cookies, and the context information about the invocation such as IP Address
17
+ *
18
+ * !! BEWARE !! Anything returned from this function will be available to the
19
+ * client--it becomes the content of `currentUser` on the web side (as well as
20
+ * `context.currentUser` on the api side). You should carefully add additional
21
+ * fields to the return object only once you've decided they are safe to be seen
22
+ * if someone were to open the Web Inspector in their browser.
23
+ *
24
+ * @see https://github.com/cedarjs/cedar/tree/main/packages/auth for examples
25
+ */
26
+ export const getCurrentUser = async (
27
+ decoded,
28
+ /* eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars */
29
+ { token, type },
30
+ /* eslint-disable-next-line no-unused-vars, @typescript-eslint/no-unused-vars */
31
+ { event, context }
32
+ ) => {
33
+ return decoded
34
+ }
35
+
36
+ /**
37
+ * The user is authenticated if there is a currentUser in the context
38
+ *
39
+ * @returns {boolean} - If the currentUser is authenticated
40
+ */
41
+ export const isAuthenticated = (): boolean => {
42
+ return !!context.currentUser
43
+ }
44
+
45
+ /**
46
+ * Call requireAuth in your services, or use the @requireAuth directive to check that a user is logged in,
47
+ * and raise an error if they're not.
48
+ *
49
+ * @returns - If the currentUser is authenticated
50
+ *
51
+ * @throws {@link AuthenticationError} - If the currentUser is not authenticated
52
+ *
53
+ * @see https://github.com/cedarjs/cedar/tree/main/packages/auth for examples
54
+ */
55
+ export const requireAuth = () => {
56
+ if (!isAuthenticated()) {
57
+ throw new AuthenticationError("You don't have permission to do that.")
58
+ }
59
+
60
+ // Custom RBAC implementation required for firebase
61
+ // https://firebase.google.com/docs/auth/admin/custom-claims
62
+ }
@@ -0,0 +1,34 @@
1
+ 'use client'
2
+
3
+ import { initializeApp, getApp, getApps } from 'firebase/app'
4
+ import * as firebaseAuth from 'firebase/auth'
5
+
6
+ import { createAuth } from '@cedarjs/auth-firebase-web'
7
+
8
+ const firebaseConfig = {
9
+ apiKey: process.env.FIREBASE_API_KEY,
10
+ authDomain: process.env.FIREBASE_AUTH_DOMAIN,
11
+
12
+ // Optional config, may be needed, depending on how you use firebase
13
+ // projectId: process.env.FIREBASE_PROJECT_ID,
14
+ // storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
15
+ // messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
16
+ // appId: process.env.FIREBASE_APP_ID,
17
+ }
18
+
19
+ const firebaseApp = ((config) => {
20
+ const apps = getApps()
21
+
22
+ if (!apps.length) {
23
+ initializeApp(config)
24
+ }
25
+
26
+ return getApp()
27
+ })(firebaseConfig)
28
+
29
+ export const firebaseClient = {
30
+ firebaseAuth,
31
+ firebaseApp, // optional
32
+ }
33
+
34
+ export const { AuthProvider, useAuth } = createAuth(firebaseClient)
@@ -0,0 +1,32 @@
1
+ import { initializeApp, getApp, getApps } from 'firebase/app'
2
+ import * as firebaseAuth from 'firebase/auth'
3
+
4
+ import { createAuth } from '@cedarjs/auth-firebase-web'
5
+
6
+ const firebaseConfig = {
7
+ apiKey: process.env.FIREBASE_API_KEY,
8
+ authDomain: process.env.FIREBASE_AUTH_DOMAIN,
9
+
10
+ // Optional config, may be needed, depending on how you use firebase
11
+ // projectId: process.env.FIREBASE_PROJECT_ID,
12
+ // storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
13
+ // messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
14
+ // appId: process.env.FIREBASE_APP_ID,
15
+ }
16
+
17
+ const firebaseApp = ((config) => {
18
+ const apps = getApps()
19
+
20
+ if (!apps.length) {
21
+ initializeApp(config)
22
+ }
23
+
24
+ return getApp()
25
+ })(firebaseConfig)
26
+
27
+ export const firebaseClient = {
28
+ firebaseAuth,
29
+ firebaseApp, // optional
30
+ }
31
+
32
+ export const { AuthProvider, useAuth } = createAuth(firebaseClient)
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@cedarjs/auth-firebase-setup",
3
+ "version": "0.0.4",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "git+https://github.com/cedarjs/cedar.git",
7
+ "directory": "packages/auth-providers/firebase/setup"
8
+ },
9
+ "license": "MIT",
10
+ "type": "commonjs",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "default": "./dist/index.js"
15
+ },
16
+ "./dist/setup": {
17
+ "types": "./dist/setup.d.ts",
18
+ "default": "./dist/setup.js"
19
+ },
20
+ "./dist/setupHandler": {
21
+ "types": "./dist/setupHandler.d.ts",
22
+ "default": "./dist/setupHandler.js"
23
+ }
24
+ },
25
+ "main": "./dist/index.js",
26
+ "types": "./dist/index.d.ts",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "scripts": {
31
+ "build": "tsx ./build.mts && yarn build:types",
32
+ "build:pack": "yarn pack -o cedar-auth-firebase-setup.tgz",
33
+ "build:types": "tsc --build --verbose ./tsconfig.json",
34
+ "build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx,template\" --ignore dist --exec \"yarn build\"",
35
+ "check:attw": "yarn attw -P",
36
+ "check:package": "concurrently npm:check:attw yarn:publint",
37
+ "prepublishOnly": "NODE_ENV=production yarn build",
38
+ "test": "vitest run",
39
+ "test:watch": "vitest watch"
40
+ },
41
+ "dependencies": {
42
+ "@cedarjs/cli-helpers": "0.0.4"
43
+ },
44
+ "devDependencies": {
45
+ "@arethetypeswrong/cli": "0.16.4",
46
+ "@cedarjs/framework-tools": "0.0.4",
47
+ "@types/yargs": "17.0.33",
48
+ "concurrently": "8.2.2",
49
+ "publint": "0.3.11",
50
+ "tsx": "4.19.3",
51
+ "typescript": "5.6.2",
52
+ "vitest": "2.1.9"
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "gitHead": "5b4f77f985bd86ee31ee7338312627accf0cb85b"
58
+ }