@netlify/identity 0.1.0-alpha.6 → 0.1.0-alpha.7
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/dist/index.cjs +12 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +12 -5
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
package/dist/index.cjs
CHANGED
|
@@ -40,6 +40,9 @@ __export(index_exports, {
|
|
|
40
40
|
});
|
|
41
41
|
module.exports = __toCommonJS(index_exports);
|
|
42
42
|
|
|
43
|
+
// src/types.ts
|
|
44
|
+
var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "saml", "email"];
|
|
45
|
+
|
|
43
46
|
// src/environment.ts
|
|
44
47
|
var import_gotrue_js = __toESM(require("gotrue-js"), 1);
|
|
45
48
|
var goTrueClient = null;
|
|
@@ -78,7 +81,10 @@ var getGoTrueClient = () => {
|
|
|
78
81
|
var getIdentityContext = () => {
|
|
79
82
|
const identityContext = globalThis.netlifyIdentityContext;
|
|
80
83
|
if (identityContext?.url && typeof identityContext.url === "string") {
|
|
81
|
-
return {
|
|
84
|
+
return {
|
|
85
|
+
url: identityContext.url,
|
|
86
|
+
token: typeof identityContext.token === "string" ? identityContext.token : void 0
|
|
87
|
+
};
|
|
82
88
|
}
|
|
83
89
|
if (globalThis.Netlify?.context?.url) {
|
|
84
90
|
return { url: new URL("/.netlify/identity", globalThis.Netlify.context.url).href };
|
|
@@ -87,6 +93,7 @@ var getIdentityContext = () => {
|
|
|
87
93
|
};
|
|
88
94
|
|
|
89
95
|
// src/user.ts
|
|
96
|
+
var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
|
|
90
97
|
var toUser = (userData) => {
|
|
91
98
|
const name = userData.user_metadata.full_name || userData.user_metadata.name;
|
|
92
99
|
const pictureUrl = userData.user_metadata.avatar_url;
|
|
@@ -96,7 +103,7 @@ var toUser = (userData) => {
|
|
|
96
103
|
emailVerified: !!userData.confirmed_at,
|
|
97
104
|
createdAt: userData.created_at,
|
|
98
105
|
updatedAt: userData.updated_at,
|
|
99
|
-
provider: userData.app_metadata.provider,
|
|
106
|
+
provider: toAuthProvider(userData.app_metadata.provider),
|
|
100
107
|
name: typeof name === "string" ? name : void 0,
|
|
101
108
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
102
109
|
metadata: userData.user_metadata,
|
|
@@ -108,9 +115,9 @@ var claimsToUser = (claims) => {
|
|
|
108
115
|
const userMeta = claims.user_metadata ?? {};
|
|
109
116
|
const name = userMeta.full_name || userMeta.name;
|
|
110
117
|
return {
|
|
111
|
-
id: claims.sub,
|
|
112
|
-
email: claims.email,
|
|
113
|
-
provider: appMeta.provider,
|
|
118
|
+
id: typeof claims.sub === "string" ? claims.sub : "",
|
|
119
|
+
email: typeof claims.email === "string" ? claims.email : void 0,
|
|
120
|
+
provider: toAuthProvider(appMeta.provider),
|
|
114
121
|
name: typeof name === "string" ? name : void 0,
|
|
115
122
|
metadata: userMeta
|
|
116
123
|
};
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/environment.ts","../src/user.ts","../src/errors.ts","../src/config.ts"],"sourcesContent":["export type { User } from './user.js'\nexport { toUser, getUser, isAuthenticated } from './user.js'\nexport { getIdentityConfig, getSettings } from './config.js'\nexport type { JWTClaims } from './auth.js'\nexport { AuthError, MissingIdentityError } from './errors.js'\nexport type { AppMetadata, AuthProvider, IdentityConfig, Settings } from './types.js'\n","import GoTrue from 'gotrue-js'\n\nimport type { IdentityConfig } from './types.js'\n\nlet goTrueClient: GoTrue | null = null\nlet cachedApiUrl: string | null | undefined\nlet warnedMissingUrl = false\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined' && typeof window.location !== 'undefined'\n\n/**\n * Discovers and caches the GoTrue API URL.\n *\n * Browser: uses `window.location.origin` + `/.netlify/identity`.\n * Server: reads from `globalThis.netlifyIdentityContext`.\n */\nconst discoverApiUrl = (): string | null => {\n if (cachedApiUrl !== undefined) return cachedApiUrl\n\n if (isBrowser()) {\n cachedApiUrl = `${window.location.origin}/.netlify/identity`\n } else {\n const identityContext = getIdentityContext()\n if (identityContext?.url) {\n cachedApiUrl = identityContext.url\n } else if (globalThis.Netlify?.context?.url) {\n cachedApiUrl = new URL('/.netlify/identity', globalThis.Netlify.context.url).href\n }\n }\n\n return cachedApiUrl ?? null\n}\n\n/**\n * Returns (and lazily creates) a singleton gotrue-js client.\n * Returns `null` and logs a warning if no identity URL can be discovered.\n */\nexport const getGoTrueClient = (): GoTrue | null => {\n if (goTrueClient) return goTrueClient\n\n const apiUrl = discoverApiUrl()\n if (!apiUrl) {\n if (!warnedMissingUrl) {\n console.warn(\n '@netlify/identity: Could not determine the Identity endpoint URL. ' +\n 'Make sure your site has Netlify Identity enabled, or run your app with `netlify dev`.',\n )\n warnedMissingUrl = true\n }\n return null\n }\n\n goTrueClient = new GoTrue({ APIUrl: apiUrl, setCookie: isBrowser() })\n return goTrueClient\n}\n\n/**\n * Reads the server-side identity context set by the Netlify bootstrap.\n * Returns `null` outside the Netlify serverless environment.\n */\nexport const getIdentityContext = (): IdentityConfig | null => {\n const identityContext = globalThis.netlifyIdentityContext\n if (identityContext?.url && typeof identityContext.url === 'string') {\n return { url: identityContext.url, token: typeof identityContext.token === 'string' ? identityContext.token : undefined }\n }\n\n if (globalThis.Netlify?.context?.url) {\n return { url: new URL('/.netlify/identity', globalThis.Netlify.context.url).href }\n }\n\n return null\n}\n\n/** Reset cached state for tests. */\nexport const resetTestGoTrueClient = (): void => {\n goTrueClient = null\n cachedApiUrl = undefined\n warnedMissingUrl = false\n}\n","import type { UserData } from 'gotrue-js'\nimport type { AuthProvider } from './types.js'\nimport { getGoTrueClient, isBrowser } from './environment.js'\n\nexport interface User {\n id: string\n email?: string\n emailVerified?: boolean\n createdAt?: string\n updatedAt?: string\n provider?: AuthProvider\n name?: string\n pictureUrl?: string\n metadata?: Record<string, unknown>\n rawGoTrueData?: Record<string, unknown>\n}\n\nexport const toUser = (userData: UserData): User => {\n const name = userData.user_metadata.full_name || userData.user_metadata.name\n const pictureUrl = userData.user_metadata.avatar_url\n\n return {\n id: userData.id,\n email: userData.email,\n emailVerified: !!userData.confirmed_at,\n createdAt: userData.created_at,\n updatedAt: userData.updated_at,\n provider: userData.app_metadata.provider as AuthProvider,\n name: typeof name === 'string' ? name : undefined,\n pictureUrl: typeof pictureUrl === 'string' ? pictureUrl : undefined,\n metadata: userData.user_metadata,\n rawGoTrueData: { ...userData },\n }\n}\n\n/**\n * Converts raw JWT claims from the identity header into a User.\n * JWT claims use a different shape than the gotrue-js UserData class.\n */\nconst claimsToUser = (claims: Record<string, unknown>): User => {\n const appMeta = (claims.app_metadata ?? {}) as Record<string, unknown>\n const userMeta = (claims.user_metadata ?? {}) as Record<string, unknown>\n const name = userMeta.full_name || userMeta.name\n\n return {\n id: claims.sub as string,\n email: claims.email as string | undefined,\n provider: appMeta.provider as AuthProvider | undefined,\n name: typeof name === 'string' ? name : undefined,\n metadata: userMeta,\n }\n}\n\n/**\n * Returns the currently authenticated user, or `null` if not logged in.\n * Synchronous. Never throws.\n */\nexport const getUser = (): User | null => {\n if (isBrowser()) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser() ?? null\n if (!currentUser) return null\n return toUser(currentUser)\n }\n\n const identityContext = globalThis.netlifyIdentityContext\n if (!identityContext) return null\n\n const claims = identityContext.user ?? (identityContext.sub ? identityContext : null)\n if (!claims) return null\n return claimsToUser(claims as Record<string, unknown>)\n}\n\n/**\n * Returns `true` if a user is currently authenticated.\n */\nexport const isAuthenticated = (): boolean => getUser() !== null\n","export class AuthError extends Error {\n override name = 'AuthError'\n status?: number\n declare cause?: unknown\n\n constructor(message: string, status?: number, options?: { cause?: unknown }) {\n super(message)\n this.status = status\n if (options && 'cause' in options) {\n this.cause = options.cause\n }\n }\n}\n\nexport class MissingIdentityError extends Error {\n override name = 'MissingIdentityError'\n\n constructor(message = 'Identity is not available in this environment') {\n super(message)\n }\n}\n","import type { IdentityConfig, Settings } from './types.js'\nimport { AuthError, MissingIdentityError } from './errors.js'\nimport { getGoTrueClient, getIdentityContext, isBrowser } from './environment.js'\n\n/**\n * Returns the identity configuration for the current environment.\n * Browser: always returns `{ url }` derived from `window.location.origin`.\n * Server: returns `{ url, token }` from the identity context, or `null` if unavailable.\n * Never throws.\n */\nexport const getIdentityConfig = (): IdentityConfig | null => {\n if (isBrowser()) {\n return { url: `${window.location.origin}/.netlify/identity` }\n }\n\n return getIdentityContext()\n}\n\n/**\n * Fetches the GoTrue `/settings` endpoint.\n * Throws `MissingIdentityError` if Identity is not configured.\n * Throws `AuthError` if the endpoint is unreachable.\n */\nexport const getSettings = async (): Promise<Settings> => {\n const client = getGoTrueClient()\n if (!client) throw new MissingIdentityError()\n\n try {\n const raw = await client.settings()\n const external = raw.external ?? {}\n return {\n autoconfirm: raw.autoconfirm,\n disableSignup: raw.disable_signup,\n providers: {\n google: external.google ?? false,\n github: external.github ?? false,\n gitlab: external.gitlab ?? false,\n bitbucket: external.bitbucket ?? false,\n facebook: external.facebook ?? false,\n email: external.email ?? false,\n saml: false,\n },\n }\n } catch (err) {\n throw new AuthError(err instanceof Error ? err.message : 'Failed to fetch identity settings', 502, { cause: err })\n }\n}\n"],"mappings":"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","names":["GoTrue"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/types.ts","../src/environment.ts","../src/user.ts","../src/errors.ts","../src/config.ts"],"sourcesContent":["export type { User } from './user.js'\nexport { toUser, getUser, isAuthenticated } from './user.js'\nexport { getIdentityConfig, getSettings } from './config.js'\nexport type { JWTClaims } from './auth.js'\nexport { AuthError, MissingIdentityError } from './errors.js'\nexport type { AppMetadata, AuthProvider, IdentityConfig, Settings } from './types.js'\n","export const AUTH_PROVIDERS = ['google', 'github', 'gitlab', 'bitbucket', 'facebook', 'saml', 'email'] as const\nexport type AuthProvider = (typeof AUTH_PROVIDERS)[number]\n\nexport interface AppMetadata {\n provider: AuthProvider\n roles?: string[]\n [key: string]: unknown\n}\n\nexport interface IdentityConfig {\n url: string\n token?: string // this is an operator token, only available on the server\n}\n\nexport interface Settings {\n autoconfirm: boolean\n disableSignup: boolean\n providers: Record<AuthProvider, boolean>\n}\n","import GoTrue from 'gotrue-js'\n\nimport type { IdentityConfig } from './types.js'\n\nlet goTrueClient: GoTrue | null = null\nlet cachedApiUrl: string | null | undefined\nlet warnedMissingUrl = false\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined' && typeof window.location !== 'undefined'\n\n/**\n * Discovers and caches the GoTrue API URL.\n *\n * Browser: uses `window.location.origin` + `/.netlify/identity`.\n * Server: reads from `globalThis.netlifyIdentityContext`.\n */\nconst discoverApiUrl = (): string | null => {\n if (cachedApiUrl !== undefined) return cachedApiUrl\n\n if (isBrowser()) {\n cachedApiUrl = `${window.location.origin}/.netlify/identity`\n } else {\n const identityContext = getIdentityContext()\n if (identityContext?.url) {\n cachedApiUrl = identityContext.url\n } else if (globalThis.Netlify?.context?.url) {\n cachedApiUrl = new URL('/.netlify/identity', globalThis.Netlify.context.url).href\n }\n }\n\n return cachedApiUrl ?? null\n}\n\n/**\n * Returns (and lazily creates) a singleton gotrue-js client.\n * Returns `null` and logs a warning if no identity URL can be discovered.\n */\nexport const getGoTrueClient = (): GoTrue | null => {\n if (goTrueClient) return goTrueClient\n\n const apiUrl = discoverApiUrl()\n if (!apiUrl) {\n if (!warnedMissingUrl) {\n console.warn(\n '@netlify/identity: Could not determine the Identity endpoint URL. ' +\n 'Make sure your site has Netlify Identity enabled, or run your app with `netlify dev`.',\n )\n warnedMissingUrl = true\n }\n return null\n }\n\n goTrueClient = new GoTrue({ APIUrl: apiUrl, setCookie: isBrowser() })\n return goTrueClient\n}\n\n/**\n * Reads the server-side identity context set by the Netlify bootstrap.\n * Returns `null` outside the Netlify serverless environment.\n */\nexport const getIdentityContext = (): IdentityConfig | null => {\n // TODO(kh): After Stargate wrapper PR deploys, netlifyIdentityContext will have\n // typed `url` and `token` fields. Remove the typeof guards and use direct access.\n const identityContext = globalThis.netlifyIdentityContext\n if (identityContext?.url && typeof identityContext.url === 'string') {\n return {\n url: identityContext.url,\n token: typeof identityContext.token === 'string' ? identityContext.token : undefined,\n }\n }\n\n if (globalThis.Netlify?.context?.url) {\n return { url: new URL('/.netlify/identity', globalThis.Netlify.context.url).href }\n }\n\n return null\n}\n\n/** Reset cached state for tests. */\nexport const resetTestGoTrueClient = (): void => {\n goTrueClient = null\n cachedApiUrl = undefined\n warnedMissingUrl = false\n}\n","import type { UserData } from 'gotrue-js'\nimport { AUTH_PROVIDERS, type AuthProvider } from './types.js'\nimport { getGoTrueClient, isBrowser } from './environment.js'\n\nconst toAuthProvider = (value: unknown): AuthProvider | undefined =>\n typeof value === 'string' && (AUTH_PROVIDERS as readonly string[]).includes(value)\n ? (value as AuthProvider)\n : undefined\n\nexport interface User {\n id: string\n email?: string\n emailVerified?: boolean\n createdAt?: string\n updatedAt?: string\n provider?: AuthProvider\n name?: string\n pictureUrl?: string\n metadata?: Record<string, unknown>\n rawGoTrueData?: Record<string, unknown>\n}\n\nexport const toUser = (userData: UserData): User => {\n const name = userData.user_metadata.full_name || userData.user_metadata.name\n const pictureUrl = userData.user_metadata.avatar_url\n\n return {\n id: userData.id,\n email: userData.email,\n emailVerified: !!userData.confirmed_at,\n createdAt: userData.created_at,\n updatedAt: userData.updated_at,\n provider: toAuthProvider(userData.app_metadata.provider),\n name: typeof name === 'string' ? name : undefined,\n pictureUrl: typeof pictureUrl === 'string' ? pictureUrl : undefined,\n metadata: userData.user_metadata,\n rawGoTrueData: { ...userData },\n }\n}\n\n/**\n * Converts raw JWT claims from the identity header into a User.\n * JWT claims use a different shape than the gotrue-js UserData class.\n */\nconst claimsToUser = (claims: Record<string, unknown>): User => {\n const appMeta = (claims.app_metadata ?? {}) as Record<string, unknown>\n const userMeta = (claims.user_metadata ?? {}) as Record<string, unknown>\n const name = userMeta.full_name || userMeta.name\n\n return {\n id: typeof claims.sub === 'string' ? claims.sub : '',\n email: typeof claims.email === 'string' ? claims.email : undefined,\n provider: toAuthProvider(appMeta.provider),\n name: typeof name === 'string' ? name : undefined,\n metadata: userMeta,\n }\n}\n\n/**\n * Returns the currently authenticated user, or `null` if not logged in.\n * Synchronous. Never throws.\n */\nexport const getUser = (): User | null => {\n if (isBrowser()) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser() ?? null\n if (!currentUser) return null\n return toUser(currentUser)\n }\n\n const identityContext = globalThis.netlifyIdentityContext\n if (!identityContext) return null\n\n const claims = identityContext.user ?? (identityContext.sub ? identityContext : null)\n if (!claims) return null\n return claimsToUser(claims as Record<string, unknown>)\n}\n\n/**\n * Returns `true` if a user is currently authenticated.\n */\nexport const isAuthenticated = (): boolean => getUser() !== null\n","export class AuthError extends Error {\n override name = 'AuthError'\n status?: number\n declare cause?: unknown\n\n constructor(message: string, status?: number, options?: { cause?: unknown }) {\n super(message)\n this.status = status\n if (options && 'cause' in options) {\n this.cause = options.cause\n }\n }\n}\n\nexport class MissingIdentityError extends Error {\n override name = 'MissingIdentityError'\n\n constructor(message = 'Identity is not available in this environment') {\n super(message)\n }\n}\n","import type { IdentityConfig, Settings } from './types.js'\nimport { AuthError, MissingIdentityError } from './errors.js'\nimport { getGoTrueClient, getIdentityContext, isBrowser } from './environment.js'\n\n/**\n * Returns the identity configuration for the current environment.\n * Browser: always returns `{ url }` derived from `window.location.origin`.\n * Server: returns `{ url, token }` from the identity context, or `null` if unavailable.\n * Never throws.\n */\nexport const getIdentityConfig = (): IdentityConfig | null => {\n if (isBrowser()) {\n return { url: `${window.location.origin}/.netlify/identity` }\n }\n\n return getIdentityContext()\n}\n\n/**\n * Fetches the GoTrue `/settings` endpoint.\n * Throws `MissingIdentityError` if Identity is not configured.\n * Throws `AuthError` if the endpoint is unreachable.\n */\nexport const getSettings = async (): Promise<Settings> => {\n const client = getGoTrueClient()\n if (!client) throw new MissingIdentityError()\n\n try {\n const raw = await client.settings()\n const external = raw.external ?? {}\n return {\n autoconfirm: raw.autoconfirm,\n disableSignup: raw.disable_signup,\n providers: {\n google: external.google ?? false,\n github: external.github ?? false,\n gitlab: external.gitlab ?? false,\n bitbucket: external.bitbucket ?? false,\n facebook: external.facebook ?? false,\n email: external.email ?? false,\n saml: false,\n },\n }\n } catch (err) {\n throw new AuthError(err instanceof Error ? err.message : 'Failed to fetch identity settings', 502, { cause: err })\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,iBAAiB,CAAC,UAAU,UAAU,UAAU,aAAa,YAAY,QAAQ,OAAO;;;ACArG,uBAAmB;AAInB,IAAI,eAA8B;AAClC,IAAI;AACJ,IAAI,mBAAmB;AAEhB,IAAM,YAAY,MAAe,OAAO,WAAW,eAAe,OAAO,OAAO,aAAa;AAQpG,IAAM,iBAAiB,MAAqB;AAC1C,MAAI,iBAAiB,OAAW,QAAO;AAEvC,MAAI,UAAU,GAAG;AACf,mBAAe,GAAG,OAAO,SAAS,MAAM;AAAA,EAC1C,OAAO;AACL,UAAM,kBAAkB,mBAAmB;AAC3C,QAAI,iBAAiB,KAAK;AACxB,qBAAe,gBAAgB;AAAA,IACjC,WAAW,WAAW,SAAS,SAAS,KAAK;AAC3C,qBAAe,IAAI,IAAI,sBAAsB,WAAW,QAAQ,QAAQ,GAAG,EAAE;AAAA,IAC/E;AAAA,EACF;AAEA,SAAO,gBAAgB;AACzB;AAMO,IAAM,kBAAkB,MAAqB;AAClD,MAAI,aAAc,QAAO;AAEzB,QAAM,SAAS,eAAe;AAC9B,MAAI,CAAC,QAAQ;AACX,QAAI,CAAC,kBAAkB;AACrB,cAAQ;AAAA,QACN;AAAA,MAEF;AACA,yBAAmB;AAAA,IACrB;AACA,WAAO;AAAA,EACT;AAEA,iBAAe,IAAI,iBAAAA,QAAO,EAAE,QAAQ,QAAQ,WAAW,UAAU,EAAE,CAAC;AACpE,SAAO;AACT;AAMO,IAAM,qBAAqB,MAA6B;AAG7D,QAAM,kBAAkB,WAAW;AACnC,MAAI,iBAAiB,OAAO,OAAO,gBAAgB,QAAQ,UAAU;AACnE,WAAO;AAAA,MACL,KAAK,gBAAgB;AAAA,MACrB,OAAO,OAAO,gBAAgB,UAAU,WAAW,gBAAgB,QAAQ;AAAA,IAC7E;AAAA,EACF;AAEA,MAAI,WAAW,SAAS,SAAS,KAAK;AACpC,WAAO,EAAE,KAAK,IAAI,IAAI,sBAAsB,WAAW,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAAA,EACnF;AAEA,SAAO;AACT;;;ACxEA,IAAM,iBAAiB,CAAC,UACtB,OAAO,UAAU,YAAa,eAAqC,SAAS,KAAK,IAC5E,QACD;AAeC,IAAM,SAAS,CAAC,aAA6B;AAClD,QAAM,OAAO,SAAS,cAAc,aAAa,SAAS,cAAc;AACxE,QAAM,aAAa,SAAS,cAAc;AAE1C,SAAO;AAAA,IACL,IAAI,SAAS;AAAA,IACb,OAAO,SAAS;AAAA,IAChB,eAAe,CAAC,CAAC,SAAS;AAAA,IAC1B,WAAW,SAAS;AAAA,IACpB,WAAW,SAAS;AAAA,IACpB,UAAU,eAAe,SAAS,aAAa,QAAQ;AAAA,IACvD,MAAM,OAAO,SAAS,WAAW,OAAO;AAAA,IACxC,YAAY,OAAO,eAAe,WAAW,aAAa;AAAA,IAC1D,UAAU,SAAS;AAAA,IACnB,eAAe,EAAE,GAAG,SAAS;AAAA,EAC/B;AACF;AAMA,IAAM,eAAe,CAAC,WAA0C;AAC9D,QAAM,UAAW,OAAO,gBAAgB,CAAC;AACzC,QAAM,WAAY,OAAO,iBAAiB,CAAC;AAC3C,QAAM,OAAO,SAAS,aAAa,SAAS;AAE5C,SAAO;AAAA,IACL,IAAI,OAAO,OAAO,QAAQ,WAAW,OAAO,MAAM;AAAA,IAClD,OAAO,OAAO,OAAO,UAAU,WAAW,OAAO,QAAQ;AAAA,IACzD,UAAU,eAAe,QAAQ,QAAQ;AAAA,IACzC,MAAM,OAAO,SAAS,WAAW,OAAO;AAAA,IACxC,UAAU;AAAA,EACZ;AACF;AAMO,IAAM,UAAU,MAAmB;AACxC,MAAI,UAAU,GAAG;AACf,UAAM,SAAS,gBAAgB;AAC/B,UAAM,cAAc,QAAQ,YAAY,KAAK;AAC7C,QAAI,CAAC,YAAa,QAAO;AACzB,WAAO,OAAO,WAAW;AAAA,EAC3B;AAEA,QAAM,kBAAkB,WAAW;AACnC,MAAI,CAAC,gBAAiB,QAAO;AAE7B,QAAM,SAAS,gBAAgB,SAAS,gBAAgB,MAAM,kBAAkB;AAChF,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,aAAa,MAAiC;AACvD;AAKO,IAAM,kBAAkB,MAAe,QAAQ,MAAM;;;ACjFrD,IAAM,YAAN,cAAwB,MAAM;AAAA,EAKnC,YAAY,SAAiB,QAAiB,SAA+B;AAC3E,UAAM,OAAO;AALf,SAAS,OAAO;AAMd,SAAK,SAAS;AACd,QAAI,WAAW,WAAW,SAAS;AACjC,WAAK,QAAQ,QAAQ;AAAA,IACvB;AAAA,EACF;AACF;AAEO,IAAM,uBAAN,cAAmC,MAAM;AAAA,EAG9C,YAAY,UAAU,iDAAiD;AACrE,UAAM,OAAO;AAHf,SAAS,OAAO;AAAA,EAIhB;AACF;;;ACVO,IAAM,oBAAoB,MAA6B;AAC5D,MAAI,UAAU,GAAG;AACf,WAAO,EAAE,KAAK,GAAG,OAAO,SAAS,MAAM,qBAAqB;AAAA,EAC9D;AAEA,SAAO,mBAAmB;AAC5B;AAOO,IAAM,cAAc,YAA+B;AACxD,QAAM,SAAS,gBAAgB;AAC/B,MAAI,CAAC,OAAQ,OAAM,IAAI,qBAAqB;AAE5C,MAAI;AACF,UAAM,MAAM,MAAM,OAAO,SAAS;AAClC,UAAM,WAAW,IAAI,YAAY,CAAC;AAClC,WAAO;AAAA,MACL,aAAa,IAAI;AAAA,MACjB,eAAe,IAAI;AAAA,MACnB,WAAW;AAAA,QACT,QAAQ,SAAS,UAAU;AAAA,QAC3B,QAAQ,SAAS,UAAU;AAAA,QAC3B,QAAQ,SAAS,UAAU;AAAA,QAC3B,WAAW,SAAS,aAAa;AAAA,QACjC,UAAU,SAAS,YAAY;AAAA,QAC/B,OAAO,SAAS,SAAS;AAAA,QACzB,MAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF,SAAS,KAAK;AACZ,UAAM,IAAI,UAAU,eAAe,QAAQ,IAAI,UAAU,qCAAqC,KAAK,EAAE,OAAO,IAAI,CAAC;AAAA,EACnH;AACF;","names":["GoTrue"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { UserData } from 'gotrue-js';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
declare const AUTH_PROVIDERS: readonly ["google", "github", "gitlab", "bitbucket", "facebook", "saml", "email"];
|
|
4
|
+
type AuthProvider = (typeof AUTH_PROVIDERS)[number];
|
|
4
5
|
interface AppMetadata {
|
|
5
6
|
provider: AuthProvider;
|
|
6
7
|
roles?: string[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { UserData } from 'gotrue-js';
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
declare const AUTH_PROVIDERS: readonly ["google", "github", "gitlab", "bitbucket", "facebook", "saml", "email"];
|
|
4
|
+
type AuthProvider = (typeof AUTH_PROVIDERS)[number];
|
|
4
5
|
interface AppMetadata {
|
|
5
6
|
provider: AuthProvider;
|
|
6
7
|
roles?: string[];
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/types.ts
|
|
2
|
+
var AUTH_PROVIDERS = ["google", "github", "gitlab", "bitbucket", "facebook", "saml", "email"];
|
|
3
|
+
|
|
1
4
|
// src/environment.ts
|
|
2
5
|
import GoTrue from "gotrue-js";
|
|
3
6
|
var goTrueClient = null;
|
|
@@ -36,7 +39,10 @@ var getGoTrueClient = () => {
|
|
|
36
39
|
var getIdentityContext = () => {
|
|
37
40
|
const identityContext = globalThis.netlifyIdentityContext;
|
|
38
41
|
if (identityContext?.url && typeof identityContext.url === "string") {
|
|
39
|
-
return {
|
|
42
|
+
return {
|
|
43
|
+
url: identityContext.url,
|
|
44
|
+
token: typeof identityContext.token === "string" ? identityContext.token : void 0
|
|
45
|
+
};
|
|
40
46
|
}
|
|
41
47
|
if (globalThis.Netlify?.context?.url) {
|
|
42
48
|
return { url: new URL("/.netlify/identity", globalThis.Netlify.context.url).href };
|
|
@@ -45,6 +51,7 @@ var getIdentityContext = () => {
|
|
|
45
51
|
};
|
|
46
52
|
|
|
47
53
|
// src/user.ts
|
|
54
|
+
var toAuthProvider = (value) => typeof value === "string" && AUTH_PROVIDERS.includes(value) ? value : void 0;
|
|
48
55
|
var toUser = (userData) => {
|
|
49
56
|
const name = userData.user_metadata.full_name || userData.user_metadata.name;
|
|
50
57
|
const pictureUrl = userData.user_metadata.avatar_url;
|
|
@@ -54,7 +61,7 @@ var toUser = (userData) => {
|
|
|
54
61
|
emailVerified: !!userData.confirmed_at,
|
|
55
62
|
createdAt: userData.created_at,
|
|
56
63
|
updatedAt: userData.updated_at,
|
|
57
|
-
provider: userData.app_metadata.provider,
|
|
64
|
+
provider: toAuthProvider(userData.app_metadata.provider),
|
|
58
65
|
name: typeof name === "string" ? name : void 0,
|
|
59
66
|
pictureUrl: typeof pictureUrl === "string" ? pictureUrl : void 0,
|
|
60
67
|
metadata: userData.user_metadata,
|
|
@@ -66,9 +73,9 @@ var claimsToUser = (claims) => {
|
|
|
66
73
|
const userMeta = claims.user_metadata ?? {};
|
|
67
74
|
const name = userMeta.full_name || userMeta.name;
|
|
68
75
|
return {
|
|
69
|
-
id: claims.sub,
|
|
70
|
-
email: claims.email,
|
|
71
|
-
provider: appMeta.provider,
|
|
76
|
+
id: typeof claims.sub === "string" ? claims.sub : "",
|
|
77
|
+
email: typeof claims.email === "string" ? claims.email : void 0,
|
|
78
|
+
provider: toAuthProvider(appMeta.provider),
|
|
72
79
|
name: typeof name === "string" ? name : void 0,
|
|
73
80
|
metadata: userMeta
|
|
74
81
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/environment.ts","../src/user.ts","../src/errors.ts","../src/config.ts"],"sourcesContent":["import GoTrue from 'gotrue-js'\n\nimport type { IdentityConfig } from './types.js'\n\nlet goTrueClient: GoTrue | null = null\nlet cachedApiUrl: string | null | undefined\nlet warnedMissingUrl = false\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined' && typeof window.location !== 'undefined'\n\n/**\n * Discovers and caches the GoTrue API URL.\n *\n * Browser: uses `window.location.origin` + `/.netlify/identity`.\n * Server: reads from `globalThis.netlifyIdentityContext`.\n */\nconst discoverApiUrl = (): string | null => {\n if (cachedApiUrl !== undefined) return cachedApiUrl\n\n if (isBrowser()) {\n cachedApiUrl = `${window.location.origin}/.netlify/identity`\n } else {\n const identityContext = getIdentityContext()\n if (identityContext?.url) {\n cachedApiUrl = identityContext.url\n } else if (globalThis.Netlify?.context?.url) {\n cachedApiUrl = new URL('/.netlify/identity', globalThis.Netlify.context.url).href\n }\n }\n\n return cachedApiUrl ?? null\n}\n\n/**\n * Returns (and lazily creates) a singleton gotrue-js client.\n * Returns `null` and logs a warning if no identity URL can be discovered.\n */\nexport const getGoTrueClient = (): GoTrue | null => {\n if (goTrueClient) return goTrueClient\n\n const apiUrl = discoverApiUrl()\n if (!apiUrl) {\n if (!warnedMissingUrl) {\n console.warn(\n '@netlify/identity: Could not determine the Identity endpoint URL. ' +\n 'Make sure your site has Netlify Identity enabled, or run your app with `netlify dev`.',\n )\n warnedMissingUrl = true\n }\n return null\n }\n\n goTrueClient = new GoTrue({ APIUrl: apiUrl, setCookie: isBrowser() })\n return goTrueClient\n}\n\n/**\n * Reads the server-side identity context set by the Netlify bootstrap.\n * Returns `null` outside the Netlify serverless environment.\n */\nexport const getIdentityContext = (): IdentityConfig | null => {\n const identityContext = globalThis.netlifyIdentityContext\n if (identityContext?.url && typeof identityContext.url === 'string') {\n return { url: identityContext.url, token: typeof identityContext.token === 'string' ? identityContext.token : undefined }\n }\n\n if (globalThis.Netlify?.context?.url) {\n return { url: new URL('/.netlify/identity', globalThis.Netlify.context.url).href }\n }\n\n return null\n}\n\n/** Reset cached state for tests. */\nexport const resetTestGoTrueClient = (): void => {\n goTrueClient = null\n cachedApiUrl = undefined\n warnedMissingUrl = false\n}\n","import type { UserData } from 'gotrue-js'\nimport type { AuthProvider } from './types.js'\nimport { getGoTrueClient, isBrowser } from './environment.js'\n\nexport interface User {\n id: string\n email?: string\n emailVerified?: boolean\n createdAt?: string\n updatedAt?: string\n provider?: AuthProvider\n name?: string\n pictureUrl?: string\n metadata?: Record<string, unknown>\n rawGoTrueData?: Record<string, unknown>\n}\n\nexport const toUser = (userData: UserData): User => {\n const name = userData.user_metadata.full_name || userData.user_metadata.name\n const pictureUrl = userData.user_metadata.avatar_url\n\n return {\n id: userData.id,\n email: userData.email,\n emailVerified: !!userData.confirmed_at,\n createdAt: userData.created_at,\n updatedAt: userData.updated_at,\n provider: userData.app_metadata.provider as AuthProvider,\n name: typeof name === 'string' ? name : undefined,\n pictureUrl: typeof pictureUrl === 'string' ? pictureUrl : undefined,\n metadata: userData.user_metadata,\n rawGoTrueData: { ...userData },\n }\n}\n\n/**\n * Converts raw JWT claims from the identity header into a User.\n * JWT claims use a different shape than the gotrue-js UserData class.\n */\nconst claimsToUser = (claims: Record<string, unknown>): User => {\n const appMeta = (claims.app_metadata ?? {}) as Record<string, unknown>\n const userMeta = (claims.user_metadata ?? {}) as Record<string, unknown>\n const name = userMeta.full_name || userMeta.name\n\n return {\n id: claims.sub as string,\n email: claims.email as string | undefined,\n provider: appMeta.provider as AuthProvider | undefined,\n name: typeof name === 'string' ? name : undefined,\n metadata: userMeta,\n }\n}\n\n/**\n * Returns the currently authenticated user, or `null` if not logged in.\n * Synchronous. Never throws.\n */\nexport const getUser = (): User | null => {\n if (isBrowser()) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser() ?? null\n if (!currentUser) return null\n return toUser(currentUser)\n }\n\n const identityContext = globalThis.netlifyIdentityContext\n if (!identityContext) return null\n\n const claims = identityContext.user ?? (identityContext.sub ? identityContext : null)\n if (!claims) return null\n return claimsToUser(claims as Record<string, unknown>)\n}\n\n/**\n * Returns `true` if a user is currently authenticated.\n */\nexport const isAuthenticated = (): boolean => getUser() !== null\n","export class AuthError extends Error {\n override name = 'AuthError'\n status?: number\n declare cause?: unknown\n\n constructor(message: string, status?: number, options?: { cause?: unknown }) {\n super(message)\n this.status = status\n if (options && 'cause' in options) {\n this.cause = options.cause\n }\n }\n}\n\nexport class MissingIdentityError extends Error {\n override name = 'MissingIdentityError'\n\n constructor(message = 'Identity is not available in this environment') {\n super(message)\n }\n}\n","import type { IdentityConfig, Settings } from './types.js'\nimport { AuthError, MissingIdentityError } from './errors.js'\nimport { getGoTrueClient, getIdentityContext, isBrowser } from './environment.js'\n\n/**\n * Returns the identity configuration for the current environment.\n * Browser: always returns `{ url }` derived from `window.location.origin`.\n * Server: returns `{ url, token }` from the identity context, or `null` if unavailable.\n * Never throws.\n */\nexport const getIdentityConfig = (): IdentityConfig | null => {\n if (isBrowser()) {\n return { url: `${window.location.origin}/.netlify/identity` }\n }\n\n return getIdentityContext()\n}\n\n/**\n * Fetches the GoTrue `/settings` endpoint.\n * Throws `MissingIdentityError` if Identity is not configured.\n * Throws `AuthError` if the endpoint is unreachable.\n */\nexport const getSettings = async (): Promise<Settings> => {\n const client = getGoTrueClient()\n if (!client) throw new MissingIdentityError()\n\n try {\n const raw = await client.settings()\n const external = raw.external ?? {}\n return {\n autoconfirm: raw.autoconfirm,\n disableSignup: raw.disable_signup,\n providers: {\n google: external.google ?? false,\n github: external.github ?? false,\n gitlab: external.gitlab ?? false,\n bitbucket: external.bitbucket ?? false,\n facebook: external.facebook ?? false,\n email: external.email ?? false,\n saml: false,\n },\n }\n } catch (err) {\n throw new AuthError(err instanceof Error ? err.message : 'Failed to fetch identity settings', 502, { cause: err })\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/environment.ts","../src/user.ts","../src/errors.ts","../src/config.ts"],"sourcesContent":["export const AUTH_PROVIDERS = ['google', 'github', 'gitlab', 'bitbucket', 'facebook', 'saml', 'email'] as const\nexport type AuthProvider = (typeof AUTH_PROVIDERS)[number]\n\nexport interface AppMetadata {\n provider: AuthProvider\n roles?: string[]\n [key: string]: unknown\n}\n\nexport interface IdentityConfig {\n url: string\n token?: string // this is an operator token, only available on the server\n}\n\nexport interface Settings {\n autoconfirm: boolean\n disableSignup: boolean\n providers: Record<AuthProvider, boolean>\n}\n","import GoTrue from 'gotrue-js'\n\nimport type { IdentityConfig } from './types.js'\n\nlet goTrueClient: GoTrue | null = null\nlet cachedApiUrl: string | null | undefined\nlet warnedMissingUrl = false\n\nexport const isBrowser = (): boolean => typeof window !== 'undefined' && typeof window.location !== 'undefined'\n\n/**\n * Discovers and caches the GoTrue API URL.\n *\n * Browser: uses `window.location.origin` + `/.netlify/identity`.\n * Server: reads from `globalThis.netlifyIdentityContext`.\n */\nconst discoverApiUrl = (): string | null => {\n if (cachedApiUrl !== undefined) return cachedApiUrl\n\n if (isBrowser()) {\n cachedApiUrl = `${window.location.origin}/.netlify/identity`\n } else {\n const identityContext = getIdentityContext()\n if (identityContext?.url) {\n cachedApiUrl = identityContext.url\n } else if (globalThis.Netlify?.context?.url) {\n cachedApiUrl = new URL('/.netlify/identity', globalThis.Netlify.context.url).href\n }\n }\n\n return cachedApiUrl ?? null\n}\n\n/**\n * Returns (and lazily creates) a singleton gotrue-js client.\n * Returns `null` and logs a warning if no identity URL can be discovered.\n */\nexport const getGoTrueClient = (): GoTrue | null => {\n if (goTrueClient) return goTrueClient\n\n const apiUrl = discoverApiUrl()\n if (!apiUrl) {\n if (!warnedMissingUrl) {\n console.warn(\n '@netlify/identity: Could not determine the Identity endpoint URL. ' +\n 'Make sure your site has Netlify Identity enabled, or run your app with `netlify dev`.',\n )\n warnedMissingUrl = true\n }\n return null\n }\n\n goTrueClient = new GoTrue({ APIUrl: apiUrl, setCookie: isBrowser() })\n return goTrueClient\n}\n\n/**\n * Reads the server-side identity context set by the Netlify bootstrap.\n * Returns `null` outside the Netlify serverless environment.\n */\nexport const getIdentityContext = (): IdentityConfig | null => {\n // TODO(kh): After Stargate wrapper PR deploys, netlifyIdentityContext will have\n // typed `url` and `token` fields. Remove the typeof guards and use direct access.\n const identityContext = globalThis.netlifyIdentityContext\n if (identityContext?.url && typeof identityContext.url === 'string') {\n return {\n url: identityContext.url,\n token: typeof identityContext.token === 'string' ? identityContext.token : undefined,\n }\n }\n\n if (globalThis.Netlify?.context?.url) {\n return { url: new URL('/.netlify/identity', globalThis.Netlify.context.url).href }\n }\n\n return null\n}\n\n/** Reset cached state for tests. */\nexport const resetTestGoTrueClient = (): void => {\n goTrueClient = null\n cachedApiUrl = undefined\n warnedMissingUrl = false\n}\n","import type { UserData } from 'gotrue-js'\nimport { AUTH_PROVIDERS, type AuthProvider } from './types.js'\nimport { getGoTrueClient, isBrowser } from './environment.js'\n\nconst toAuthProvider = (value: unknown): AuthProvider | undefined =>\n typeof value === 'string' && (AUTH_PROVIDERS as readonly string[]).includes(value)\n ? (value as AuthProvider)\n : undefined\n\nexport interface User {\n id: string\n email?: string\n emailVerified?: boolean\n createdAt?: string\n updatedAt?: string\n provider?: AuthProvider\n name?: string\n pictureUrl?: string\n metadata?: Record<string, unknown>\n rawGoTrueData?: Record<string, unknown>\n}\n\nexport const toUser = (userData: UserData): User => {\n const name = userData.user_metadata.full_name || userData.user_metadata.name\n const pictureUrl = userData.user_metadata.avatar_url\n\n return {\n id: userData.id,\n email: userData.email,\n emailVerified: !!userData.confirmed_at,\n createdAt: userData.created_at,\n updatedAt: userData.updated_at,\n provider: toAuthProvider(userData.app_metadata.provider),\n name: typeof name === 'string' ? name : undefined,\n pictureUrl: typeof pictureUrl === 'string' ? pictureUrl : undefined,\n metadata: userData.user_metadata,\n rawGoTrueData: { ...userData },\n }\n}\n\n/**\n * Converts raw JWT claims from the identity header into a User.\n * JWT claims use a different shape than the gotrue-js UserData class.\n */\nconst claimsToUser = (claims: Record<string, unknown>): User => {\n const appMeta = (claims.app_metadata ?? {}) as Record<string, unknown>\n const userMeta = (claims.user_metadata ?? {}) as Record<string, unknown>\n const name = userMeta.full_name || userMeta.name\n\n return {\n id: typeof claims.sub === 'string' ? claims.sub : '',\n email: typeof claims.email === 'string' ? claims.email : undefined,\n provider: toAuthProvider(appMeta.provider),\n name: typeof name === 'string' ? name : undefined,\n metadata: userMeta,\n }\n}\n\n/**\n * Returns the currently authenticated user, or `null` if not logged in.\n * Synchronous. Never throws.\n */\nexport const getUser = (): User | null => {\n if (isBrowser()) {\n const client = getGoTrueClient()\n const currentUser = client?.currentUser() ?? null\n if (!currentUser) return null\n return toUser(currentUser)\n }\n\n const identityContext = globalThis.netlifyIdentityContext\n if (!identityContext) return null\n\n const claims = identityContext.user ?? (identityContext.sub ? identityContext : null)\n if (!claims) return null\n return claimsToUser(claims as Record<string, unknown>)\n}\n\n/**\n * Returns `true` if a user is currently authenticated.\n */\nexport const isAuthenticated = (): boolean => getUser() !== null\n","export class AuthError extends Error {\n override name = 'AuthError'\n status?: number\n declare cause?: unknown\n\n constructor(message: string, status?: number, options?: { cause?: unknown }) {\n super(message)\n this.status = status\n if (options && 'cause' in options) {\n this.cause = options.cause\n }\n }\n}\n\nexport class MissingIdentityError extends Error {\n override name = 'MissingIdentityError'\n\n constructor(message = 'Identity is not available in this environment') {\n super(message)\n }\n}\n","import type { IdentityConfig, Settings } from './types.js'\nimport { AuthError, MissingIdentityError } from './errors.js'\nimport { getGoTrueClient, getIdentityContext, isBrowser } from './environment.js'\n\n/**\n * Returns the identity configuration for the current environment.\n * Browser: always returns `{ url }` derived from `window.location.origin`.\n * Server: returns `{ url, token }` from the identity context, or `null` if unavailable.\n * Never throws.\n */\nexport const getIdentityConfig = (): IdentityConfig | null => {\n if (isBrowser()) {\n return { url: `${window.location.origin}/.netlify/identity` }\n }\n\n return getIdentityContext()\n}\n\n/**\n * Fetches the GoTrue `/settings` endpoint.\n * Throws `MissingIdentityError` if Identity is not configured.\n * Throws `AuthError` if the endpoint is unreachable.\n */\nexport const getSettings = async (): Promise<Settings> => {\n const client = getGoTrueClient()\n if (!client) throw new MissingIdentityError()\n\n try {\n const raw = await client.settings()\n const external = raw.external ?? {}\n return {\n autoconfirm: raw.autoconfirm,\n disableSignup: raw.disable_signup,\n providers: {\n google: external.google ?? false,\n github: external.github ?? false,\n gitlab: external.gitlab ?? false,\n bitbucket: external.bitbucket ?? false,\n facebook: external.facebook ?? false,\n email: external.email ?? false,\n saml: false,\n },\n }\n } catch (err) {\n throw new AuthError(err instanceof Error ? err.message : 'Failed to fetch identity settings', 502, { cause: err })\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@netlify/identity",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.7",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Add authentication to your Netlify site with a few lines of code",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -33,10 +33,12 @@
|
|
|
33
33
|
"test": "vitest run",
|
|
34
34
|
"test:watch": "vitest",
|
|
35
35
|
"lint": "eslint src test",
|
|
36
|
+
"typecheck": "tsc --noEmit",
|
|
36
37
|
"format": "prettier --check .",
|
|
37
38
|
"format:fix": "prettier --write .",
|
|
38
39
|
"prepack": "npm run build",
|
|
39
|
-
"prepublishOnly": "npm run test"
|
|
40
|
+
"prepublishOnly": "npm run test",
|
|
41
|
+
"prepare": "husky"
|
|
40
42
|
},
|
|
41
43
|
"keywords": [
|
|
42
44
|
"netlify",
|
|
@@ -55,13 +57,18 @@
|
|
|
55
57
|
"author": "Netlify Inc.",
|
|
56
58
|
"devDependencies": {
|
|
57
59
|
"eslint": "^9.0.0",
|
|
60
|
+
"husky": "^9.1.7",
|
|
58
61
|
"jsdom": "^28.1.0",
|
|
62
|
+
"lint-staged": "^16.2.7",
|
|
59
63
|
"prettier": "^3.0.0",
|
|
60
64
|
"tsup": "^8.5.0",
|
|
61
65
|
"typescript": "^5.0.0",
|
|
62
66
|
"typescript-eslint": "^8.0.0",
|
|
63
67
|
"vitest": "^4.0.0"
|
|
64
68
|
},
|
|
69
|
+
"lint-staged": {
|
|
70
|
+
"*.{ts,js,json,md}": "prettier --write"
|
|
71
|
+
},
|
|
65
72
|
"dependencies": {
|
|
66
73
|
"gotrue-js": "^1.0.1"
|
|
67
74
|
}
|