cloudcommerce 0.0.73 → 0.0.74

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/package.json +8 -8
  3. package/packages/api/package.json +1 -1
  4. package/packages/apps/correios/package.json +1 -1
  5. package/packages/apps/custom-shipping/package.json +1 -1
  6. package/packages/apps/discounts/package.json +1 -1
  7. package/packages/apps/frenet/package.json +1 -1
  8. package/packages/apps/tiny-erp/package.json +1 -1
  9. package/packages/cli/config/firebase.json +47 -0
  10. package/packages/cli/package.json +1 -1
  11. package/packages/config/package.json +1 -1
  12. package/packages/events/package.json +1 -1
  13. package/packages/firebase/package.json +1 -1
  14. package/packages/modules/package.json +2 -1
  15. package/packages/modules/schemas/@checkout.cjs +28 -28
  16. package/packages/modules/schemas/apply_discount.cjs +2 -2
  17. package/packages/modules/schemas/calculate_shipping.cjs +4 -4
  18. package/packages/modules/schemas/create_transaction.cjs +30 -30
  19. package/packages/modules/schemas/list_payments.cjs +6 -6
  20. package/packages/modules/src/firebase/ajv.ts +2 -1
  21. package/packages/modules/src/firebase/handle-module.ts +5 -1
  22. package/packages/modules/src/firebase/serve-modules-api.ts +5 -3
  23. package/packages/passport/lib/firebase/handle-passport.js +96 -92
  24. package/packages/passport/lib/firebase/serve-passport-api.js +35 -34
  25. package/packages/passport/lib/firebase.js +5 -7
  26. package/packages/passport/lib/index.js +2 -1
  27. package/packages/passport/package.json +1 -1
  28. package/packages/ssr/lib/firebase/serve-storefront.js +33 -33
  29. package/packages/ssr/lib/firebase.js +2 -4
  30. package/packages/ssr/lib/index.js +1 -2
  31. package/packages/ssr/package.json +1 -1
  32. package/packages/storefront/astro.config.mjs +2 -0
  33. package/packages/storefront/dist/client/LoginModal.d6b935cf.js +1 -0
  34. package/packages/storefront/dist/client/assets/{_...c08e0a75.css → _...27b7eb4d.css} +1 -1
  35. package/packages/storefront/dist/client/assets/_...b3f65c5c.css +1 -0
  36. package/packages/storefront/dist/client/assets/fallback-index.90217cf0.css +1 -0
  37. package/packages/storefront/dist/client/assets/{fallback.9745a8aa.css → fallback.9cd2ed3f.css} +1 -1
  38. package/packages/storefront/dist/client/assets/{index.9745690c.css → index.c5a9ea80.css} +1 -1
  39. package/packages/storefront/dist/client/chunks/index.esm.69f70489.js +1726 -0
  40. package/packages/storefront/dist/client/chunks/index.esm2017.1194d1a1.js +457 -0
  41. package/packages/storefront/dist/client/chunks/runtime-core.esm-bundler.a7337834.js +1 -0
  42. package/packages/storefront/dist/client/client.80b904f3.js +1 -0
  43. package/packages/storefront/dist/client/hoisted.24787260.js +376 -0
  44. package/packages/storefront/dist/server/entry.mjs +342 -69
  45. package/packages/storefront/package.json +11 -9
  46. package/packages/storefront/src/assets/firebaseui.css +648 -0
  47. package/packages/storefront/src/lib/components/LoginModal.vue +42 -9
  48. package/packages/storefront/src/lib/layouts/Layout.astro +24 -0
  49. package/packages/types/package.json +1 -1
  50. package/packages/apps/tiny-erp/lib/event-to-tiny.js +0 -115
  51. package/packages/apps/tiny-erp/lib/event-to-tiny.js.map +0 -1
  52. package/packages/apps/tiny-erp/lib/index.js +0 -2
  53. package/packages/apps/tiny-erp/lib/index.js.map +0 -1
  54. package/packages/apps/tiny-erp/lib/integration/after-tiny-queue.js +0 -79
  55. package/packages/apps/tiny-erp/lib/integration/after-tiny-queue.js.map +0 -1
  56. package/packages/apps/tiny-erp/lib/integration/export-order-to-tiny.js +0 -84
  57. package/packages/apps/tiny-erp/lib/integration/export-order-to-tiny.js.map +0 -1
  58. package/packages/apps/tiny-erp/lib/integration/export-product-to-tiny.js +0 -58
  59. package/packages/apps/tiny-erp/lib/integration/export-product-to-tiny.js.map +0 -1
  60. package/packages/apps/tiny-erp/lib/integration/helpers/format-tiny-date.js +0 -7
  61. package/packages/apps/tiny-erp/lib/integration/helpers/format-tiny-date.js.map +0 -1
  62. package/packages/apps/tiny-erp/lib/integration/import-order-from-tiny.js +0 -92
  63. package/packages/apps/tiny-erp/lib/integration/import-order-from-tiny.js.map +0 -1
  64. package/packages/apps/tiny-erp/lib/integration/import-product-from-tiny.js +0 -158
  65. package/packages/apps/tiny-erp/lib/integration/import-product-from-tiny.js.map +0 -1
  66. package/packages/apps/tiny-erp/lib/integration/parsers/order-from-tiny.js +0 -46
  67. package/packages/apps/tiny-erp/lib/integration/parsers/order-from-tiny.js.map +0 -1
  68. package/packages/apps/tiny-erp/lib/integration/parsers/order-to-tiny.js +0 -193
  69. package/packages/apps/tiny-erp/lib/integration/parsers/order-to-tiny.js.map +0 -1
  70. package/packages/apps/tiny-erp/lib/integration/parsers/product-from-tiny.js +0 -199
  71. package/packages/apps/tiny-erp/lib/integration/parsers/product-from-tiny.js.map +0 -1
  72. package/packages/apps/tiny-erp/lib/integration/parsers/product-to-tiny.js +0 -129
  73. package/packages/apps/tiny-erp/lib/integration/parsers/product-to-tiny.js.map +0 -1
  74. package/packages/apps/tiny-erp/lib/integration/parsers/status-from-tiny.js +0 -34
  75. package/packages/apps/tiny-erp/lib/integration/parsers/status-from-tiny.js.map +0 -1
  76. package/packages/apps/tiny-erp/lib/integration/parsers/status-to-tiny.js +0 -39
  77. package/packages/apps/tiny-erp/lib/integration/parsers/status-to-tiny.js.map +0 -1
  78. package/packages/apps/tiny-erp/lib/integration/post-tiny-erp.js +0 -47
  79. package/packages/apps/tiny-erp/lib/integration/post-tiny-erp.js.map +0 -1
  80. package/packages/apps/tiny-erp/lib/tiny-erp.js +0 -18
  81. package/packages/apps/tiny-erp/lib/tiny-erp.js.map +0 -1
  82. package/packages/apps/tiny-erp/lib/tiny-webhook.js +0 -92
  83. package/packages/apps/tiny-erp/lib/tiny-webhook.js.map +0 -1
  84. package/packages/modules/lib/firebase/ajv.js +0 -33
  85. package/packages/modules/lib/firebase/ajv.js.map +0 -1
  86. package/packages/modules/lib/firebase/call-app-module.js +0 -135
  87. package/packages/modules/lib/firebase/call-app-module.js.map +0 -1
  88. package/packages/modules/lib/firebase/checkout.js +0 -1
  89. package/packages/modules/lib/firebase/checkout.js.map +0 -1
  90. package/packages/modules/lib/firebase/handle-module.js +0 -165
  91. package/packages/modules/lib/firebase/handle-module.js.map +0 -1
  92. package/packages/modules/lib/firebase/proxy-apps.js +0 -1
  93. package/packages/modules/lib/firebase/proxy-apps.js.map +0 -1
  94. package/packages/modules/lib/firebase/serve-modules-api.js +0 -57
  95. package/packages/modules/lib/firebase/serve-modules-api.js.map +0 -1
  96. package/packages/modules/lib/firebase.js +0 -13
  97. package/packages/modules/lib/firebase.js.map +0 -1
  98. package/packages/modules/lib/index.js +0 -25
  99. package/packages/modules/lib/index.js.map +0 -1
  100. package/packages/storefront/dist/client/assets/_...d4aa8aff.css +0 -1
  101. package/packages/storefront/dist/client/assets/fallback-index.d9230d24.css +0 -1
  102. package/packages/storefront/dist/client/client.6d48c590.js +0 -1
@@ -18,7 +18,9 @@ export default (req: Request, res: Response) => {
18
18
  if (url.endsWith('.json')) {
19
19
  url = url.slice(0, -5);
20
20
  }
21
+ [url] = url.split('?');
21
22
  const modName = url.split('/')[1];
23
+
22
24
  const sendSchema = (isResponseSchema = false) => {
23
25
  return res.status(200)
24
26
  .setHeader('Cache-Control', 'public, max-age=3600')
@@ -41,11 +43,11 @@ export default (req: Request, res: Response) => {
41
43
  if (schemas[modName]) {
42
44
  const { params: schema, response: responseSchema } = schemas[modName];
43
45
  if (!schema.$schema) {
44
- schema.$schema = 'http://json-schema.org/draft-06/schema#';
46
+ schema.$schema = 'http://json-schema.org/draft-07/schema#';
45
47
  schema.title = `Module \`${modName}\`: Params model`;
46
48
  }
47
49
  if (!responseSchema.$schema) {
48
- responseSchema.$schema = 'http://json-schema.org/draft-06/schema#';
50
+ responseSchema.$schema = 'http://json-schema.org/draft-07/schema#';
49
51
  responseSchema.title = `Module \`${modName}\`: App response model`;
50
52
  }
51
53
  if (url === `/${modName}/schema`) {
@@ -55,7 +57,7 @@ export default (req: Request, res: Response) => {
55
57
  return sendSchema(true);
56
58
  }
57
59
  if (url === `/${modName}`) {
58
- return handleModule(modName, schema, responseSchema, req, res);
60
+ return handleModule(modName, schema, responseSchema, req, res)[method]();
59
61
  }
60
62
  }
61
63
  return res.sendStatus(404);
@@ -1,110 +1,114 @@
1
1
  import { logger } from 'firebase-functions';
2
2
  import api from '@cloudcommerce/api';
3
3
  import getEnv from '@cloudcommerce/firebase/lib/env';
4
-
5
4
  const findCustomerByEmail = async (email) => {
6
- try {
7
- const { data } = await api.get(`customers?main_email=${email}`);
8
- if (data.result.length) {
9
- return data.result[0];
5
+ try {
6
+ const { data } = await api.get(`customers?main_email=${email}`);
7
+ if (data.result.length) {
8
+ return data.result[0];
9
+ }
10
+ return null;
11
+ }
12
+ catch (e) {
13
+ logger.error(e);
14
+ return null;
10
15
  }
11
- return null;
12
- } catch (e) {
13
- logger.error(e);
14
- return null;
15
- }
16
16
  };
17
17
  const checkFirebaseAuth = async (auth, authToken) => {
18
- if (authToken && !Array.isArray(authToken)) {
19
- try {
20
- const customer = await auth.verifyIdToken(authToken);
21
- return customer;
22
- } catch (e) {
23
- return null;
18
+ if (authToken && !Array.isArray(authToken)) {
19
+ try {
20
+ const customer = await auth.verifyIdToken(authToken);
21
+ return customer;
22
+ }
23
+ catch (e) {
24
+ return null;
25
+ }
26
+ }
27
+ else {
28
+ return null;
24
29
  }
25
- } else {
26
- return null;
27
- }
28
30
  };
29
31
  const createCustomer = async (customer) => {
30
- try {
31
- const { data } = await api.post('customers', customer);
32
- return data._id;
33
- } catch (e) {
34
- logger.error(e);
35
- return null;
36
- }
32
+ try {
33
+ const { data } = await api.post('customers', customer);
34
+ return data._id;
35
+ }
36
+ catch (e) {
37
+ logger.error(e);
38
+ return null;
39
+ }
37
40
  };
38
41
  const generateAccessToken = async (firestore, customerId) => {
39
- const { apiAuth } = getEnv();
40
- const docRef = firestore.doc(`customerTokens/${customerId}`);
41
- const doc = await docRef.get();
42
- const expires = doc.data()?.expires;
43
- if (expires && new Date(expires).getTime() - Date.now() >= 2 * 60 * 1000) {
44
- return doc.data();
45
- }
46
- try {
47
- const { data } = await api({
48
- endpoint: 'authenticate',
49
- method: 'post',
50
- body: {
51
- _id: apiAuth.authenticationId,
52
- api_key: apiAuth.apiKey,
53
- customer_id: customerId,
54
- },
55
- });
56
- const accessToken = {
57
- access_token: data.access_token,
58
- expires: data.expires,
59
- customer_id: customerId,
60
- };
61
- docRef.set(accessToken).catch(logger.error);
62
- return accessToken;
63
- } catch (e) {
64
- logger.error(e);
65
- return null;
66
- }
42
+ const { apiAuth } = getEnv();
43
+ const docRef = firestore.doc(`customerTokens/${customerId}`);
44
+ const doc = await docRef.get();
45
+ const expires = doc.data()?.expires;
46
+ if (expires && new Date(expires).getTime() - Date.now() >= 2 * 60 * 1000) {
47
+ return doc.data();
48
+ }
49
+ try {
50
+ const { data } = await api({
51
+ endpoint: 'authenticate',
52
+ method: 'post',
53
+ body: {
54
+ _id: apiAuth.authenticationId,
55
+ api_key: apiAuth.apiKey,
56
+ customer_id: customerId,
57
+ },
58
+ });
59
+ const accessToken = {
60
+ access_token: data.access_token,
61
+ expires: data.expires,
62
+ customer_id: customerId,
63
+ };
64
+ docRef.set(accessToken).catch(logger.error);
65
+ return accessToken;
66
+ }
67
+ catch (e) {
68
+ logger.error(e);
69
+ return null;
70
+ }
67
71
  };
68
72
  const getAuthCustomerApi = async (firestore, authtoken, authFirebase) => {
69
- const customerFirebaseAuth = await checkFirebaseAuth(authFirebase, authtoken);
70
- if (customerFirebaseAuth !== null && customerFirebaseAuth.email) {
71
- const customer = await findCustomerByEmail(customerFirebaseAuth.email);
72
- if (customer !== null) {
73
- return generateAccessToken(firestore, customer._id);
74
- }
75
- const newCustomer = {
76
- display_name: customerFirebaseAuth.name || '',
77
- main_email: customerFirebaseAuth.email,
78
- emails: [{
79
- address: customerFirebaseAuth.email,
80
- verified: customerFirebaseAuth.email_verified,
81
- }],
82
- oauth_providers: [{
83
- provider: customerFirebaseAuth.firebase.sign_in_provider,
84
- user_id: customerFirebaseAuth.user_id,
85
- }],
86
- };
87
- const customerId = await createCustomer(newCustomer);
88
- if (customerId) {
89
- return generateAccessToken(firestore, customerId);
73
+ const customerFirebaseAuth = await checkFirebaseAuth(authFirebase, authtoken);
74
+ if (customerFirebaseAuth !== null && customerFirebaseAuth.email) {
75
+ const customer = await findCustomerByEmail(customerFirebaseAuth.email);
76
+ if (customer !== null) {
77
+ return generateAccessToken(firestore, customer._id);
78
+ }
79
+ const newCustomer = {
80
+ display_name: customerFirebaseAuth.name || '',
81
+ main_email: customerFirebaseAuth.email,
82
+ emails: [{
83
+ address: customerFirebaseAuth.email,
84
+ verified: customerFirebaseAuth.email_verified,
85
+ }],
86
+ oauth_providers: [{
87
+ provider: customerFirebaseAuth.firebase.sign_in_provider,
88
+ user_id: customerFirebaseAuth.user_id,
89
+ }],
90
+ };
91
+ const customerId = await createCustomer(newCustomer);
92
+ if (customerId) {
93
+ return generateAccessToken(firestore, customerId);
94
+ }
90
95
  }
91
- }
92
- // TODO: Find customer by phone number, generate token if found, otherwise unauthorize
93
- return null;
96
+ // TODO: Find customer by phone number, generate token if found, otherwise unauthorize
97
+ return null;
94
98
  };
95
99
  const sendError = (res, msg, status = 400) => {
96
- if (msg) {
97
- res.status(status).json({
98
- status,
99
- error: msg,
100
- });
101
- } else {
102
- res.status(500).json({
103
- status: 500,
104
- error: 'Internal server error',
105
- });
106
- }
100
+ if (msg) {
101
+ res.status(status).json({
102
+ status,
103
+ error: msg,
104
+ });
105
+ }
106
+ else {
107
+ res.status(500).json({
108
+ status: 500,
109
+ error: 'Internal server error',
110
+ });
111
+ }
107
112
  };
108
-
109
- export { sendError, getAuthCustomerApi };
110
- // # sourceMappingURL=handle-passport.js.map
113
+ export { sendError, getAuthCustomerApi, };
114
+ //# sourceMappingURL=handle-passport.js.map
@@ -1,41 +1,42 @@
1
1
  import { logger } from 'firebase-functions';
2
- import { sendError, getAuthCustomerApi } from './handle-passport.js';
3
-
2
+ import { sendError, getAuthCustomerApi, } from './handle-passport.js';
4
3
  export default async (req, res, firestore, authFirebase, storeId) => {
5
- const { method } = req;
6
- if (method !== 'POST') {
7
- return res.sendStatus(405);
8
- }
9
- if (method === 'POST'
4
+ const { method } = req;
5
+ if (method !== 'POST') {
6
+ return res.sendStatus(405);
7
+ }
8
+ if (method === 'POST'
10
9
  && (!req.body || typeof req.body !== 'object' || Array.isArray(req.body))) {
11
- return res.sendStatus(400);
12
- }
13
- let { url } = req;
14
- if (url.endsWith('.json')) {
15
- url = url.slice(0, -5);
16
- }
17
- const endpoint = url.split('/')[1];
18
- // endpoint /token
19
- if (endpoint === 'token' && method === 'POST') {
20
- const { authtoken } = req.body;
21
- if (!firestore) {
22
- return sendError(res, 'Firestore not found', 500);
10
+ return res.sendStatus(400);
11
+ }
12
+ let { url } = req;
13
+ if (url.endsWith('.json')) {
14
+ url = url.slice(0, -5);
23
15
  }
24
- if (storeId < 100) {
25
- return sendError(res, 'Invalid store');
16
+ const endpoint = url.split('/')[1];
17
+ // endpoint /token
18
+ if (endpoint === 'token' && method === 'POST') {
19
+ const { authtoken } = req.body;
20
+ if (!firestore) {
21
+ return sendError(res, 'Firestore not found', 500);
22
+ }
23
+ if (storeId < 100) {
24
+ return sendError(res, 'Invalid store');
25
+ }
26
+ try {
27
+ const authCustomerApi = await getAuthCustomerApi(firestore, authtoken, authFirebase);
28
+ if (authCustomerApi !== null) {
29
+ return res.send(authCustomerApi);
30
+ }
31
+ return sendError(res, 'Invalid token, unauthorized', 401);
32
+ }
33
+ catch (e) {
34
+ logger.error(e);
35
+ return sendError(res);
36
+ }
26
37
  }
27
- try {
28
- const authCustomerApi = await getAuthCustomerApi(firestore, authtoken, authFirebase);
29
- if (authCustomerApi !== null) {
30
- return res.send(authCustomerApi);
31
- }
32
- return sendError(res, 'Invalid token, unauthorized', 401);
33
- } catch (e) {
34
- logger.error(e);
35
- return sendError(res);
38
+ else {
39
+ return res.sendStatus(400);
36
40
  }
37
- } else {
38
- return res.sendStatus(400);
39
- }
40
41
  };
41
- // # sourceMappingURL=serve-passport-api.js.map
42
+ //# sourceMappingURL=serve-passport-api.js.map
@@ -7,7 +7,6 @@ import { getAuth } from 'firebase-admin/auth';
7
7
  import { onRequest } from 'firebase-functions/v2/https';
8
8
  import config from '@cloudcommerce/firebase/lib/config';
9
9
  import servePassportApi from './firebase/serve-passport-api.js';
10
-
11
10
  // References:
12
11
  // https:// firebase.google.com/docs/auth/admin/manage-cookies
13
12
  // https://itnext.io/how-to-use-firebase-auth-with-a-custom-node-backend-99a106376c8a
@@ -16,13 +15,12 @@ import servePassportApi from './firebase/serve-passport-api.js';
16
15
  const authFirebase = getAuth();
17
16
  const firestore = getFirestore();
18
17
  const options = {
19
- ...config.get().httpsFunctionOptions,
20
- memory: '128MiB',
18
+ ...config.get().httpsFunctionOptions,
19
+ memory: '128MiB',
21
20
  };
22
-
23
21
  // eslint-disable-next-line import/prefer-default-export
24
22
  export const passport = onRequest(options, (req, res) => {
25
- const { storeId } = config.get();
26
- servePassportApi(req, res, firestore, authFirebase, storeId);
23
+ const { storeId } = config.get();
24
+ servePassportApi(req, res, firestore, authFirebase, storeId);
27
25
  });
28
- // # sourceMappingURL=firebase.js.map
26
+ //# sourceMappingURL=firebase.js.map
@@ -1 +1,2 @@
1
- // # sourceMappingURL=index.js.map
1
+ "use strict";
2
+ //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/passport",
3
3
  "type": "module",
4
- "version": "0.0.73",
4
+ "version": "0.0.74",
5
5
  "description": "E-Com Plus Cloud Commerce customers authentication (passport) API",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -1,49 +1,49 @@
1
1
  import { join as joinPath } from 'path';
2
2
  import { readFile } from 'fs/promises';
3
-
4
3
  const { STOREFRONT_BASE_DIR } = process.env;
5
4
  const baseDir = STOREFRONT_BASE_DIR || process.cwd();
6
5
  const clientRoot = new URL(joinPath(baseDir, 'dist/client/'), import.meta.url);
7
-
8
6
  export default (req, res) => {
9
- const url = req.url.replace(/\?.*$/, '').replace(/\.html$/, '');
10
- const setStatusAndCache = (status, defaultCache) => {
11
- return res.status(status)
12
- .set('X-SSR-ID', `v1/${Math.random()}`)
13
- .set('Cache-Control', (typeof global.cache_control === 'function' && global.cache_control(status))
7
+ const url = req.url.replace(/\?.*$/, '').replace(/\.html$/, '');
8
+ const setStatusAndCache = (status, defaultCache) => {
9
+ return res.status(status)
10
+ .set('X-SSR-ID', `v1/${Math.random()}`)
11
+ .set('Cache-Control', (typeof global.cache_control === 'function' && global.cache_control(status))
14
12
  || defaultCache);
15
- };
16
- const fallback = (err, status = 500) => {
17
- if (url !== '/fallback' && (/\/[^/.]+$/.test(url) || /\.x?html$/.test(url))) {
18
- setStatusAndCache(status, 'public, max-age=120')
19
- .send('<html><head>'
13
+ };
14
+ const fallback = (err, status = 500) => {
15
+ if (url !== '/fallback' && (/\/[^/.]+$/.test(url) || /\.x?html$/.test(url))) {
16
+ setStatusAndCache(status, 'public, max-age=120')
17
+ .send('<html><head>'
20
18
  + '<meta http-equiv="refresh" content="0; '
21
19
  + `url=/fallback?status=${status}&url=${encodeURIComponent(url)}"/>`
22
20
  + `</head><body>${err.toString()}</body></html>`);
23
- } else {
24
- setStatusAndCache(status, 'public, max-age=120, s-maxage=600')
25
- .send(err.toString());
26
- }
27
- };
21
+ }
22
+ else {
23
+ setStatusAndCache(status, 'public, max-age=120, s-maxage=600')
24
+ .send(err.toString());
25
+ }
26
+ };
28
27
  /*
29
28
  https://github.com/withastro/astro/blob/main/examples/ssr/server/server.mjs
30
29
  import { handler as ssrHandler } from '../dist/server/entry.mjs';
31
30
  global.ssr_handler = ssrHandler;
32
31
  */
33
- global.ssr_handler(req, res, async (err) => {
34
- if (err) {
35
- res.set('X-SSR-Error', err.message);
36
- fallback(err);
37
- return;
38
- }
39
- const local = new URL(`.${url}`, clientRoot);
40
- try {
41
- const data = await readFile(local);
42
- setStatusAndCache(200, 'public, max-age=60, s-maxage=600')
43
- .send(data);
44
- } catch {
45
- fallback(err, 404);
46
- }
47
- });
32
+ global.ssr_handler(req, res, async (err) => {
33
+ if (err) {
34
+ res.set('X-SSR-Error', err.message);
35
+ fallback(err);
36
+ return;
37
+ }
38
+ const local = new URL(`.${url}`, clientRoot);
39
+ try {
40
+ const data = await readFile(local);
41
+ setStatusAndCache(200, 'public, max-age=60, s-maxage=600')
42
+ .send(data);
43
+ }
44
+ catch {
45
+ fallback(err, 404);
46
+ }
47
+ });
48
48
  };
49
- // # sourceMappingURL=serve-storefront.js.map
49
+ //# sourceMappingURL=serve-storefront.js.map
@@ -4,10 +4,8 @@ import '@cloudcommerce/firebase/lib/init';
4
4
  import { onRequest } from 'firebase-functions/v2/https';
5
5
  import config from '@cloudcommerce/firebase/lib/config';
6
6
  import serveStorefront from './firebase/serve-storefront.js';
7
-
8
7
  const { httpsFunctionOptions } = config.get();
9
-
10
8
  export const ssr = onRequest(httpsFunctionOptions, (req, res) => {
11
- serveStorefront(req, res);
9
+ serveStorefront(req, res);
12
10
  });
13
- // # sourceMappingURL=firebase.js.map
11
+ //# sourceMappingURL=firebase.js.map
@@ -1,4 +1,3 @@
1
1
  import serveStorefront from './firebase/serve-storefront.js';
2
-
3
2
  export default serveStorefront;
4
- // # sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cloudcommerce/ssr",
3
3
  "type": "module",
4
- "version": "0.0.73",
4
+ "version": "0.0.74",
5
5
  "description": "E-Com Plus Cloud Commerce storefront SSR",
6
6
  "main": "lib/index.js",
7
7
  "exports": {
@@ -4,6 +4,7 @@ import * as dotenv from 'dotenv';
4
4
  import { defineConfig } from 'astro/config';
5
5
  import node from '@astrojs/node';
6
6
  import vue from '@astrojs/vue';
7
+ import image from '@astrojs/image';
7
8
  import partytown from '@astrojs/partytown';
8
9
  import prefetch from '@astrojs/prefetch';
9
10
  import sitemap from '@astrojs/sitemap';
@@ -17,6 +18,7 @@ export default defineConfig({
17
18
  adapter: node(),
18
19
  integrations: [
19
20
  vue(),
21
+ image(),
20
22
  partytown(),
21
23
  prefetch(),
22
24
  sitemap(),
@@ -0,0 +1 @@
1
+ import{r as w,c as j,a as g,t as k,b as T,F as x,o as N}from"./chunks/runtime-core.esm-bundler.a7337834.js";/* empty css */const v="modulepreload",M=function(r){return"/"+r},U={},D=function(c,a,d){return!a||a.length===0?c():Promise.all(a.map(u=>{if(u=M(u),u in U)return;U[u]=!0;const _=u.endsWith(".css"),y=_?'[rel="stylesheet"]':"";if(document.querySelector(`link[href="${u}"]${y}`))return;const i=document.createElement("link");if(i.rel=_?"stylesheet":v,_||(i.as="script",i.crossOrigin=""),i.href=u,document.head.appendChild(i),_)return new Promise((E,A)=>{i.addEventListener("load",E),i.addEventListener("error",()=>A(new Error(`Unable to preload CSS for ${u}`)))})})).then(()=>c())};var C={exports:{}};function R(r){function c(e){return e!=="constructor"&&e!=="prototype"&&e!=="__proto__"}function a(e){let t=0;const n=e.length,o=new Array(n);for(t=0;t<n;++t)o[t]=m(e[t]);return o}function d(e){const t={},n=i(e);let o,s,l;for(o=0,s=n.length;o<s;++o)c(l=n[o])&&(t[l]=m(e[l]));return t}function u(e,t){const n=e.length,o=t.length;let s=0;const l=new Array(n+o);for(s=0;s<n;++s)l[s]=m(e[s]);for(s=0;s<o;++s)l[s+n]=m(t[s]);return l}const _=Object.prototype.propertyIsEnumerable;function y(e){const t=Object.keys(e),n=Object.getOwnPropertySymbols(e);for(let o=0,s=n.length;o<s;++o)_.call(e,n[o])&&t.push(n[o]);return t}const i=r&&r.symbols?y:Object.keys;function E(e){return typeof e=="object"&&e!==null&&!(e instanceof RegExp)&&!(e instanceof Date)}function A(e){return typeof e!="object"||e===null}function I(e){return typeof e!="object"||e===null||e instanceof RegExp||e instanceof Date}const L=r&&typeof r.mergeArray=="function"?r.mergeArray({clone:m,deepmerge:b,getKeys:i,isMergeableObject:E}):u;function m(e){return E(e)?Array.isArray(e)?a(e):d(e):e}function P(e,t){const n={},o=i(e),s=i(t);let l,h,f;for(l=0,h=o.length;l<h;++l)c(f=o[l])&&s.indexOf(f)===-1&&(n[f]=m(e[f]));for(l=0,h=s.length;l<h;++l)c(f=s[l])&&(f in e&&(o.indexOf(f)!==-1&&(n[f]=b(e[f],t[f])),!0)||(n[f]=m(t[f])));return n}function b(e,t){const n=Array.isArray(t),o=Array.isArray(e);return A(t)?t:I(e)?m(t):n&&o?L(e,t):n!==o?m(t):P(e,t)}function S(){switch(arguments.length){case 0:return{};case 1:return m(arguments[0]);case 2:return b(arguments[0],arguments[1])}let e;for(let t=0,n=arguments.length;t<n;++t)e=b(e,arguments[t]);return e}return r&&r.all?S:b}C.exports=R;C.exports.default=R;C.exports.deepmerge=R;const $="pt_br",B="BRL",Y="R$",F="BR",p={BASE_URL:"/",MODE:"production",DEV:!1,PROD:!0},K=C.exports(),O=globalThis.__cloudCommerce||{config:{}};globalThis.__cloudCommerce=O;const V={get(){return{lang:p.ECOM_LANG||$,currency:p.ECOM_CURRENCY||B,currencySymbol:p.ECOM_CURRENCY_SYMBOL||Y,countryCode:p.ECOM_COUNTRY_CODE||F,storeId:Number(p.ECOM_STORE_ID),...O.config}},set(r){O.config=K(O.config,r),r.storeId&&(p.ECOM_STORE_ID=r.storeId)}},G=async()=>{const{lang:r}=V.get();D(()=>Promise.resolve({}),[]),await Promise.all([D(()=>import("./chunks/index.esm.69f70489.js"),["chunks/index.esm.69f70489.js","chunks/index.esm2017.1194d1a1.js"]),new Promise((_,y)=>{const i=document.createElement("script");i.src=`https://www.gstatic.com/firebasejs/ui/6.0.1/firebase-ui-auth__${r}.js`,i.onload=_,i.onerror=y,i.async=!0,document.body.appendChild(i)})]);const{firebase:c,firebaseui:a}=window,d=new a.auth.AuthUI(c.auth());console.log(c.auth);const u={signInSuccessUrl:"<url-to-redirect-to-on-success>",signInOptions:[c.auth.EmailAuthProvider.PROVIDER_ID],tosUrl:"<your-tos-url>",privacyPolicyUrl:"<your-privacy-policy-url>"};d.start("#firebaseui-auth-container",u)},q={setup(){G();const r=w(0);return{count:r,add:()=>{r.value+=1},subtract:()=>{r.value-=1}}}},W=(r,c)=>{const a=r.__vccOpts||r;for(const[d,u]of c)a[d]=u;return a},z={class:"counter"},H={class:"counter-message"},J=g("div",{id:"firebaseui-auth-container"},null,-1);function Q(r,c,a,d,u,_){return N(),j(x,null,[g("div",z,[g("button",{onClick:c[0]||(c[0]=y=>d.subtract())},"-"),g("pre",null,k(d.count),1),g("button",{onClick:c[1]||(c[1]=y=>d.add())},"+")]),g("div",H,[T(r.$slots,"default")]),J],64)}const ee=W(q,[["render",Q]]);export{ee as default};
@@ -1 +1 @@
1
- :root{--astro-gradient: linear-gradient(0deg,#4F39FA, #DA62C4)}h1:where(.astro-JWBYURAL){margin:2rem 0}main:where(.astro-JWBYURAL){margin:auto;padding:1em;max-width:60ch}.text-gradient:where(.astro-JWBYURAL){font-weight:900;background-image:var(--astro-gradient);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-size:100% 200%;background-position-y:100%;border-radius:.4rem;animation:pulse 4s ease-in-out infinite}@keyframes pulse{0%,to{background-position-y:0%}50%{background-position-y:80%}}.instructions:where(.astro-JWBYURAL){line-height:1.6;margin:1rem 0;background:#4F39FA;padding:1rem;border-radius:.4rem;color:var(--color-bg)}.instructions:where(.astro-JWBYURAL) code:where(.astro-JWBYURAL){font-size:.875em;border:.1em solid var(--color-border);border-radius:4px;padding:.15em .25em}.link-card-grid:where(.astro-JWBYURAL){display:grid;grid-template-columns:repeat(auto-fit,minmax(24ch,1fr));gap:1rem;padding:0}
1
+ :root{--astro-gradient: linear-gradient(0deg,#4F39FA, #DA62C4)}h1:where(.astro-P5QKJ2WB){margin:2rem 0}main:where(.astro-P5QKJ2WB){margin:auto;padding:1em;max-width:60ch}.text-gradient:where(.astro-P5QKJ2WB){font-weight:900;background-image:var(--astro-gradient);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-size:100% 200%;background-position-y:100%;border-radius:.4rem;animation:pulse 4s ease-in-out infinite}@keyframes pulse{0%,to{background-position-y:0%}50%{background-position-y:80%}}.instructions:where(.astro-P5QKJ2WB){line-height:1.6;margin:1rem 0;background:#4F39FA;padding:1rem;border-radius:.4rem;color:var(--color-bg)}.instructions:where(.astro-P5QKJ2WB) code:where(.astro-P5QKJ2WB){font-size:.875em;border:.1em solid var(--color-border);border-radius:4px;padding:.15em .25em}.link-card-grid:where(.astro-P5QKJ2WB){display:grid;grid-template-columns:repeat(auto-fit,minmax(24ch,1fr));gap:1rem;padding:0}
@@ -0,0 +1 @@
1
+ :root{--font-size-base: clamp(1rem, .34vw + .91rem, 1.19rem);--font-size-lg: clamp(1.2rem, .7vw + 1.2rem, 1.5rem);--font-size-xl: clamp(2.44rem, 2.38vw + 1.85rem, 3.75rem);--color-text: hsl(12, 5%, 4%);--color-bg: hsl(10, 21%, 95%);--color-border: hsl(17, 24%, 90%)}html{font-family:system-ui,sans-serif;font-size:var(--font-size-base);color:var(--color-text);background-color:var(--color-bg)}body{margin:0}h1{font-size:var(--font-size-xl)}h2{font-size:var(--font-size-lg)}code{font-family:Menlo,Monaco,Lucida Console,Liberation Mono,DejaVu Sans Mono,Bitstream Vera Sans Mono,Courier New,monospace}.counter{display:grid;font-size:2em;grid-template-columns:repeat(3,minmax(0,1fr));margin-top:2em;place-items:center}.counter-message{text-align:center}.firebaseui-container{background-color:#fff;box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;color:#000000de;direction:ltr;font:16px Roboto,arial,sans-serif;margin:0 auto;max-width:360px;overflow:visible;position:relative;text-align:left;width:100%}.firebaseui-container.mdl-card{overflow:visible}.firebaseui-card-header{padding:24px 24px 0}.firebaseui-card-content,.firebaseui-card-footer{padding:0 24px}.firebaseui-card-actions{box-sizing:border-box;display:table;font-size:14px;padding:8px 24px 24px;text-align:left;width:100%}.firebaseui-form-links{display:table-cell;vertical-align:middle;width:100%}.firebaseui-form-actions{display:table-cell;text-align:right;white-space:nowrap;width:100%}.firebaseui-title,.firebaseui-subtitle{color:#000000de;direction:ltr;font-size:20px;font-weight:500;line-height:24px;margin:0;padding:0;text-align:left}.firebaseui-title{padding-bottom:16px}.firebaseui-subtitle{margin:16px 0}.firebaseui-text{color:#000000de;direction:ltr;font-size:16px;line-height:24px;text-align:left}.firebaseui-id-page-password-recovery-email-sent p.firebaseui-text{margin:16px 0}.firebaseui-text-emphasis{font-weight:700}.firebaseui-error{color:#dd2c00;direction:ltr;font-size:12px;line-height:16px;margin:0;text-align:left}.firebaseui-text-input-error{margin:-16px 0 16px}.firebaseui-error-wrapper{min-height:16px}.firebaseui-list-item{direction:ltr;margin:0;padding:0;text-align:left}.firebaseui-hidden{display:none}.firebaseui-relative-wrapper{position:relative}.firebaseui-label{color:#0000008a;direction:ltr;font-size:16px;text-align:left}.mdl-textfield--floating-label.is-focused .mdl-textfield__label,.mdl-textfield--floating-label.is-dirty .mdl-textfield__label{color:#757575}.firebaseui-input,.firebaseui-input-invalid{border-radius:0;color:#000000de;direction:ltr;font-size:16px;width:100%}input.firebaseui-input,input.firebaseui-input-invalid{direction:ltr;text-align:left}.firebaseui-input-invalid{border-color:#dd2c00}.firebaseui-textfield{width:100%}.firebaseui-textfield.mdl-textfield .firebaseui-input{border-color:#0000001f}.firebaseui-textfield.mdl-textfield .firebaseui-label:after{background-color:#3f51b5}.firebaseui-textfield-invalid.mdl-textfield .firebaseui-input{border-color:#dd2c00}.firebaseui-textfield-invalid.mdl-textfield .firebaseui-label:after{background-color:#dd2c00}.firebaseui-button{display:inline-block;height:36px;margin-left:8px;min-width:88px}.firebaseui-link{color:#4285f4;font-variant:normal;font-weight:400;text-decoration:none}.firebaseui-link:hover{text-decoration:underline}.firebaseui-indent{margin-left:1em}.firebaseui-tos{color:#757575;direction:ltr;font-size:12px;line-height:16px;margin-bottom:24px;margin-top:0;text-align:left}.firebaseui-provider-sign-in-footer>.firebaseui-tos{text-align:center}.firebaseui-tos-list{list-style:none;text-align:right}.firebaseui-inline-list-item{display:inline-block;margin-left:5px;margin-right:5px}.firebaseui-page-provider-sign-in,.firebaseui-page-select-tenant{background:inherit}.firebaseui-idp-list,.firebaseui-tenant-list{list-style:none;margin:1em 0;padding:0}.firebaseui-idp-button,.firebaseui-tenant-button{direction:ltr;font-weight:500;height:auto;line-height:normal;max-width:220px;min-height:40px;padding:8px 16px;text-align:left;width:100%}.firebaseui-idp-list>.firebaseui-list-item,.firebaseui-tenant-list>.firebaseui-list-item{margin-bottom:15px;text-align:center}.firebaseui-idp-icon-wrapper{display:table-cell;vertical-align:middle}.firebaseui-idp-icon{border:none;display:inline-block;height:18px;vertical-align:middle;width:18px}.firebaseui-idp-favicon{border:none;display:inline-block;height:14px;margin-right:5px;vertical-align:middle;width:14px}.firebaseui-idp-text{color:#fff;display:table-cell;font-size:14px;padding-left:16px;text-transform:none;vertical-align:middle}.firebaseui-idp-text.firebaseui-idp-text-long{display:table-cell}.firebaseui-idp-text.firebaseui-idp-text-short{display:none}@media (max-width: 268px){.firebaseui-idp-text.firebaseui-idp-text-long{display:none}.firebaseui-idp-text.firebaseui-idp-text-short{display:table-cell}}@media (max-width: 320px){.firebaseui-recaptcha-container>div>div{transform:scale(.9);-webkit-transform:scale(.9);transform-origin:0 0;-webkit-transform-origin:0 0}}.firebaseui-idp-google>.firebaseui-idp-text{color:#757575}[data-provider-id="yahoo.com"]>.firebaseui-idp-icon-wrapper>.firebaseui-idp-icon{height:22px;width:22px}.firebaseui-info-bar{background-color:#f9edbe;border:1px solid #f0c36d;box-shadow:0 2px 4px #0003;-webkit-box-shadow:0 2px 4px rgba(0,0,0,.2);-moz-box-shadow:0 2px 4px rgba(0,0,0,.2);left:10%;padding:8px 16px;position:absolute;right:10%;text-align:center;top:0}.firebaseui-info-bar-message{font-size:12px;margin:0}.firebaseui-dialog{box-sizing:border-box;color:#000000de;font:16px Roboto,arial,sans-serif;height:auto;max-height:fit-content;padding:24px;text-align:left}.firebaseui-dialog-icon-wrapper{display:table-cell;vertical-align:middle}.firebaseui-dialog-icon{float:left;height:40px;margin-right:24px;width:40px}.firebaseui-progress-dialog-message{display:table-cell;font-size:16px;font-weight:400;min-height:40px;vertical-align:middle}.firebaseui-progress-dialog-loading-icon{height:28px;margin:6px 30px 6px 6px;width:28px}.firebaseui-icon-done{background-image:url(https://www.gstatic.com/images/icons/material/system/2x/done_googgreen_36dp.png);background-position:center;background-repeat:no-repeat;background-size:36px 36px}.firebaseui-phone-number{display:flex}.firebaseui-country-selector{background-image:url(https://www.gstatic.com/images/icons/material/system/1x/arrow_drop_down_grey600_18dp.png);background-position:right center;background-repeat:no-repeat;background-size:18px auto;border-radius:0;border-bottom:1px solid rgba(0,0,0,.12);color:#000000de;flex-shrink:0;font-size:16px;font-weight:400;height:initial;line-height:normal;margin:20px 24px 20px 0;padding:4px 20px 4px 0;width:90px}.firebaseui-country-selector-flag{display:inline-block;margin-right:1ex}.firebaseui-flag{background-image:url(https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/flags_sprite_2x.png);background-size:100% auto;filter:drop-shadow(1px 1px 1px rgba(0,0,0,.54));height:14px;width:24px}.firebaseui-list-box-dialog{max-height:90%;overflow:auto;padding:8px 0 0}.firebaseui-list-box-actions{padding-bottom:8px}.firebaseui-list-box-icon-wrapper{display:table-cell;padding-right:24px;vertical-align:top}.firebaseui-list-box-label-wrapper{display:table-cell;vertical-align:top}.firebaseui-list-box-dialog-button{color:#000000de;direction:ltr;font-size:16px;font-weight:400;height:initial;line-height:normal;min-height:48px;padding:14px 24px;text-align:left;text-transform:none;width:100%}.firebaseui-phone-number-error{margin-left:114px}.mdl-progress.firebaseui-busy-indicator{height:2px;left:0;position:absolute;top:55px;width:100%}.mdl-spinner.firebaseui-busy-indicator{direction:initial;height:56px;left:0;margin:auto;position:absolute;right:0;top:30%;width:56px}.firebaseui-callback-indicator-container .firebaseui-busy-indicator{top:0}.firebaseui-callback-indicator-container{height:120px}.firebaseui-new-password-component{display:inline-block;position:relative;width:100%}.firebaseui-input-floating-button{background-position:center;background-repeat:no-repeat;display:block;height:24px;position:absolute;right:0;top:20px;width:24px}.firebaseui-input-toggle-on{background-image:url(https://www.gstatic.com/images/icons/material/system/1x/visibility_black_24dp.png)}.firebaseui-input-toggle-off{background-image:url(https://www.gstatic.com/images/icons/material/system/1x/visibility_off_black_24dp.png)}.firebaseui-input-toggle-focus{opacity:.87}.firebaseui-input-toggle-blur{opacity:.38}.firebaseui-recaptcha-wrapper{display:table;margin:0 auto;padding-bottom:8px}.firebaseui-recaptcha-container{display:table-cell}.firebaseui-recaptcha-error-wrapper{caption-side:bottom;display:table-caption}.firebaseui-change-phone-number-link{display:block}.firebaseui-resend-container{direction:ltr;margin:20px 0;text-align:center}.firebaseui-id-resend-countdown{color:#00000061}.firebaseui-id-page-phone-sign-in-start .firebaseui-form-actions div{float:left}@media (max-width: 480px){.firebaseui-container{box-shadow:none;max-width:none;width:100%}.firebaseui-card-header{border-bottom:1px solid #e0e0e0;margin-bottom:16px;padding:16px 24px 0}.firebaseui-title{padding-bottom:16px}.firebaseui-card-actions{padding-right:24px}.firebaseui-busy-indicator{top:0}}.mdl-textfield__label{font-weight:400;margin-bottom:0}.firebaseui-id-page-blank,.firebaseui-id-page-spinner{background:inherit;height:64px}.firebaseui-email-sent{background-image:url(https://www.gstatic.com/firebasejs/ui/2.0.0/images/auth/success_status.png);background-position:center;background-repeat:no-repeat;background-size:64px 64px;height:64px;margin-top:16px;text-align:center}.firebaseui-text-justify{text-align:justify}
@@ -0,0 +1 @@
1
+ :root{--link-gradient: linear-gradient(45deg, #4F39FA, #DA62C4 30%, var(--color-border) 60%)}.link-card:where(.astro-ZCG72YVN){list-style:none;display:flex;padding:.15rem;background-image:var(--link-gradient);background-size:400%;border-radius:.5rem;background-position:100%;transition:background-position .6s cubic-bezier(.22,1,.36,1)}.link-card:where(.astro-ZCG72YVN)>a:where(.astro-ZCG72YVN){width:100%;text-decoration:none;line-height:1.4;padding:1em 1.3em;border-radius:.35rem;color:var(--text-color);background-color:#fff;opacity:.8}h2:where(.astro-ZCG72YVN){margin:0;transition:color .6s cubic-bezier(.22,1,.36,1)}p:where(.astro-ZCG72YVN){margin-top:.75rem;margin-bottom:0}h2:where(.astro-ZCG72YVN) span:where(.astro-ZCG72YVN){display:inline-block;transition:transform .3s cubic-bezier(.22,1,.36,1)}.link-card:where(.astro-ZCG72YVN):is(:hover,:focus-within){background-position:0}.link-card:where(.astro-ZCG72YVN):is(:hover,:focus-within) h2:where(.astro-ZCG72YVN){color:#4f39fa}.link-card:where(.astro-ZCG72YVN):is(:hover,:focus-within) h2:where(.astro-ZCG72YVN) span:where(.astro-ZCG72YVN){transform:translate(2px)}
@@ -1 +1 @@
1
- :root{--astro-gradient: linear-gradient(0deg,#4F39FA, #DA62C4)}h1:where(.astro-HIITKN5F){margin:2rem 0}main:where(.astro-HIITKN5F){margin:auto;padding:1em;max-width:60ch}.text-gradient:where(.astro-HIITKN5F){font-weight:900;background-image:var(--astro-gradient);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-size:100% 200%;background-position-y:100%;border-radius:.4rem;animation:pulse 4s ease-in-out infinite}@keyframes pulse{0%,to{background-position-y:0%}50%{background-position-y:80%}}.instructions:where(.astro-HIITKN5F){line-height:1.6;margin:1rem 0;background:#4F39FA;padding:1rem;border-radius:.4rem;color:var(--color-bg)}.instructions:where(.astro-HIITKN5F) code:where(.astro-HIITKN5F){font-size:.875em;border:.1em solid var(--color-border);border-radius:4px;padding:.15em .25em}.link-card-grid:where(.astro-HIITKN5F){display:grid;grid-template-columns:repeat(auto-fit,minmax(24ch,1fr));gap:1rem;padding:0}
1
+ :root{--astro-gradient: linear-gradient(0deg,#4F39FA, #DA62C4)}h1:where(.astro-BZIQPEHV){margin:2rem 0}main:where(.astro-BZIQPEHV){margin:auto;padding:1em;max-width:60ch}.text-gradient:where(.astro-BZIQPEHV){font-weight:900;background-image:var(--astro-gradient);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-size:100% 200%;background-position-y:100%;border-radius:.4rem;animation:pulse 4s ease-in-out infinite}@keyframes pulse{0%,to{background-position-y:0%}50%{background-position-y:80%}}.instructions:where(.astro-BZIQPEHV){line-height:1.6;margin:1rem 0;background:#4F39FA;padding:1rem;border-radius:.4rem;color:var(--color-bg)}.instructions:where(.astro-BZIQPEHV) code:where(.astro-BZIQPEHV){font-size:.875em;border:.1em solid var(--color-border);border-radius:4px;padding:.15em .25em}.link-card-grid:where(.astro-BZIQPEHV){display:grid;grid-template-columns:repeat(auto-fit,minmax(24ch,1fr));gap:1rem;padding:0}
@@ -1 +1 @@
1
- :root{--astro-gradient: linear-gradient(0deg,#4F39FA, #DA62C4)}h1:where(.astro-FWWSR4V6){margin:2rem 0}main:where(.astro-FWWSR4V6){margin:auto;padding:1em;max-width:60ch}.text-gradient:where(.astro-FWWSR4V6){font-weight:900;background-image:var(--astro-gradient);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-size:100% 200%;background-position-y:100%;border-radius:.4rem;animation:pulse 4s ease-in-out infinite}@keyframes pulse{0%,to{background-position-y:0%}50%{background-position-y:80%}}.instructions:where(.astro-FWWSR4V6){line-height:1.6;margin:1rem 0;background:#4F39FA;padding:1rem;border-radius:.4rem;color:var(--color-bg)}.instructions:where(.astro-FWWSR4V6) code:where(.astro-FWWSR4V6){font-size:.875em;border:.1em solid var(--color-border);border-radius:4px;padding:.15em .25em}.link-card-grid:where(.astro-FWWSR4V6){display:grid;grid-template-columns:repeat(auto-fit,minmax(24ch,1fr));gap:1rem;padding:0}
1
+ :root{--astro-gradient: linear-gradient(0deg,#4F39FA, #DA62C4)}h1:where(.astro-EBY2X3Y6){margin:2rem 0}main:where(.astro-EBY2X3Y6){margin:auto;padding:1em;max-width:60ch}.text-gradient:where(.astro-EBY2X3Y6){font-weight:900;background-image:var(--astro-gradient);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-size:100% 200%;background-position-y:100%;border-radius:.4rem;animation:pulse 4s ease-in-out infinite}@keyframes pulse{0%,to{background-position-y:0%}50%{background-position-y:80%}}.instructions:where(.astro-EBY2X3Y6){line-height:1.6;margin:1rem 0;background:#4F39FA;padding:1rem;border-radius:.4rem;color:var(--color-bg)}.instructions:where(.astro-EBY2X3Y6) code:where(.astro-EBY2X3Y6){font-size:.875em;border:.1em solid var(--color-border);border-radius:4px;padding:.15em .25em}.link-card-grid:where(.astro-EBY2X3Y6){display:grid;grid-template-columns:repeat(auto-fit,minmax(24ch,1fr));gap:1rem;padding:0}